aboutsummaryrefslogtreecommitdiffstats
path: root/embed
diff options
context:
space:
mode:
authorChristian Persch <chpe@src.gnome.org>2007-08-26 04:59:04 +0800
committerChristian Persch <chpe@src.gnome.org>2007-08-26 04:59:04 +0800
commit6deabce61b1758b0c395678bf5c2769ee4ca17c6 (patch)
tree27866c89b34cb0fe866753fbef2894e6dfd01785 /embed
parentd2bc7076ca31996d4a5b80b74e4380e6f2f56321 (diff)
downloadgsoc2013-epiphany-6deabce61b1758b0c395678bf5c2769ee4ca17c6.tar
gsoc2013-epiphany-6deabce61b1758b0c395678bf5c2769ee4ca17c6.tar.gz
gsoc2013-epiphany-6deabce61b1758b0c395678bf5c2769ee4ca17c6.tar.bz2
gsoc2013-epiphany-6deabce61b1758b0c395678bf5c2769ee4ca17c6.tar.lz
gsoc2013-epiphany-6deabce61b1758b0c395678bf5c2769ee4ca17c6.tar.xz
gsoc2013-epiphany-6deabce61b1758b0c395678bf5c2769ee4ca17c6.tar.zst
gsoc2013-epiphany-6deabce61b1758b0c395678bf5c2769ee4ca17c6.zip
Initial checkin: merged embed/gecko from xulrunner branch to embed/xulrunner, and svn copied embed/mozilla to embed/xulrunner/embed. Not integreated with the build yet.
svn path=/trunk/; revision=7297
Diffstat (limited to 'embed')
-rw-r--r--embed/xulrunner/AUTHORS2
-rw-r--r--embed/xulrunner/COPYRIGHT3
-rw-r--r--embed/xulrunner/ChangeLog545
-rw-r--r--embed/xulrunner/HACKING10
-rw-r--r--embed/xulrunner/MAINTAINERS2
-rw-r--r--embed/xulrunner/Makefile.am9
-rw-r--r--embed/xulrunner/NEWS0
-rw-r--r--embed/xulrunner/PLAN26
-rw-r--r--embed/xulrunner/README0
-rw-r--r--embed/xulrunner/STATUS2
-rw-r--r--embed/xulrunner/TODO1
-rw-r--r--embed/xulrunner/bindings/Makefile.am5
-rw-r--r--embed/xulrunner/bindings/python/Makefile.am63
-rw-r--r--embed/xulrunner/bindings/python/gnomegeckoembed.defs294
-rw-r--r--embed/xulrunner/bindings/python/gnomegeckoembed.override19
-rw-r--r--embed/xulrunner/bindings/python/gnomegeckoembedmodule.c29
-rw-r--r--embed/xulrunner/bindings/python/test.py32
-rw-r--r--embed/xulrunner/data/Makefile.am3
-rw-r--r--embed/xulrunner/data/gnome-gecko-embed.pc.in11
-rw-r--r--embed/xulrunner/embed/AutoJSContextStack.cpp47
-rw-r--r--embed/xulrunner/embed/AutoJSContextStack.h41
-rw-r--r--embed/xulrunner/embed/AutoWindowModalState.cpp61
-rw-r--r--embed/xulrunner/embed/AutoWindowModalState.h38
-rw-r--r--embed/xulrunner/embed/ContentHandler.cpp479
-rw-r--r--embed/xulrunner/embed/ContentHandler.h81
-rw-r--r--embed/xulrunner/embed/EphyAboutModule.cpp725
-rw-r--r--embed/xulrunner/embed/EphyAboutModule.h65
-rw-r--r--embed/xulrunner/embed/EphyBadCertRejector.cpp68
-rw-r--r--embed/xulrunner/embed/EphyBadCertRejector.h36
-rw-r--r--embed/xulrunner/embed/EphyBrowser.cpp1614
-rw-r--r--embed/xulrunner/embed/EphyBrowser.h223
-rw-r--r--embed/xulrunner/embed/EphyContentPolicy.cpp244
-rw-r--r--embed/xulrunner/embed/EphyContentPolicy.h76
-rw-r--r--embed/xulrunner/embed/EphyDirectoryProvider.cpp106
-rw-r--r--embed/xulrunner/embed/EphyDirectoryProvider.h37
-rw-r--r--embed/xulrunner/embed/EphyFind.cpp267
-rw-r--r--embed/xulrunner/embed/EphyFind.h60
-rw-r--r--embed/xulrunner/embed/EphyHeaderSniffer.cpp442
-rw-r--r--embed/xulrunner/embed/EphyHeaderSniffer.h95
-rw-r--r--embed/xulrunner/embed/EphyHistoryListener.cpp170
-rw-r--r--embed/xulrunner/embed/EphyHistoryListener.h49
-rw-r--r--embed/xulrunner/embed/EphyPromptService.cpp888
-rw-r--r--embed/xulrunner/embed/EphyPromptService.h53
-rw-r--r--embed/xulrunner/embed/EphyRedirectChannel.cpp32
-rw-r--r--embed/xulrunner/embed/EphyRedirectChannel.h50
-rw-r--r--embed/xulrunner/embed/EphySidebar.cpp168
-rw-r--r--embed/xulrunner/embed/EphySidebar.h66
-rw-r--r--embed/xulrunner/embed/EphySingle.cpp396
-rw-r--r--embed/xulrunner/embed/EphySingle.h67
-rw-r--r--embed/xulrunner/embed/EphyUtils.cpp218
-rw-r--r--embed/xulrunner/embed/EphyUtils.h71
-rw-r--r--embed/xulrunner/embed/EventContext.cpp1105
-rw-r--r--embed/xulrunner/embed/EventContext.h78
-rw-r--r--embed/xulrunner/embed/FilePicker.cpp492
-rw-r--r--embed/xulrunner/embed/FilePicker.h62
-rw-r--r--embed/xulrunner/embed/GeckoCookiePromptService.cpp159
-rw-r--r--embed/xulrunner/embed/GeckoCookiePromptService.h43
-rw-r--r--embed/xulrunner/embed/GeckoFormSigningDialog.cpp158
-rw-r--r--embed/xulrunner/embed/GeckoFormSigningDialog.h42
-rw-r--r--embed/xulrunner/embed/GeckoPrintService.cpp756
-rw-r--r--embed/xulrunner/embed/GeckoPrintService.h54
-rw-r--r--embed/xulrunner/embed/GeckoPrintSession.cpp629
-rw-r--r--embed/xulrunner/embed/GeckoPrintSession.h94
-rw-r--r--embed/xulrunner/embed/GeckoSpellCheckEngine.cpp205
-rw-r--r--embed/xulrunner/embed/GeckoSpellCheckEngine.h52
-rw-r--r--embed/xulrunner/embed/GlobalHistory.cpp225
-rw-r--r--embed/xulrunner/embed/GlobalHistory.h68
-rw-r--r--embed/xulrunner/embed/GtkNSSClientAuthDialogs.cpp284
-rw-r--r--embed/xulrunner/embed/GtkNSSClientAuthDialogs.h45
-rw-r--r--embed/xulrunner/embed/GtkNSSDialogs.cpp1694
-rw-r--r--embed/xulrunner/embed/GtkNSSDialogs.h61
-rw-r--r--embed/xulrunner/embed/GtkNSSKeyPairDialogs.cpp216
-rw-r--r--embed/xulrunner/embed/GtkNSSKeyPairDialogs.h45
-rw-r--r--embed/xulrunner/embed/GtkNSSSecurityWarningDialogs.cpp285
-rw-r--r--embed/xulrunner/embed/GtkNSSSecurityWarningDialogs.h83
-rw-r--r--embed/xulrunner/embed/Makefile.am159
-rw-r--r--embed/xulrunner/embed/MozDownload.cpp787
-rw-r--r--embed/xulrunner/embed/MozDownload.h152
-rw-r--r--embed/xulrunner/embed/MozRegisterComponents.cpp333
-rw-r--r--embed/xulrunner/embed/MozRegisterComponents.h28
-rw-r--r--embed/xulrunner/embed/mozilla-download.cpp313
-rw-r--r--embed/xulrunner/embed/mozilla-download.h61
-rw-r--r--embed/xulrunner/embed/mozilla-embed-event.cpp221
-rw-r--r--embed/xulrunner/embed/mozilla-embed-event.h74
-rw-r--r--embed/xulrunner/embed/mozilla-embed-find.cpp198
-rw-r--r--embed/xulrunner/embed/mozilla-embed-find.h57
-rw-r--r--embed/xulrunner/embed/mozilla-embed-persist.cpp416
-rw-r--r--embed/xulrunner/embed/mozilla-embed-persist.h63
-rw-r--r--embed/xulrunner/embed/mozilla-embed-single.cpp1445
-rw-r--r--embed/xulrunner/embed/mozilla-embed-single.h57
-rw-r--r--embed/xulrunner/embed/mozilla-embed.cpp1273
-rw-r--r--embed/xulrunner/embed/mozilla-embed.h66
-rw-r--r--embed/xulrunner/embed/mozilla-notifiers.cpp1257
-rw-r--r--embed/xulrunner/embed/mozilla-notifiers.h58
-rw-r--r--embed/xulrunner/embed/mozilla-x509-cert.cpp261
-rw-r--r--embed/xulrunner/embed/mozilla-x509-cert.h63
-rw-r--r--embed/xulrunner/src/AutoJSContextStack.cpp48
-rw-r--r--embed/xulrunner/src/AutoJSContextStack.h41
-rw-r--r--embed/xulrunner/src/AutoWindowModalState.cpp43
-rw-r--r--embed/xulrunner/src/AutoWindowModalState.h38
-rw-r--r--embed/xulrunner/src/EmbedContentListener.cpp159
-rw-r--r--embed/xulrunner/src/EmbedContentListener.h63
-rw-r--r--embed/xulrunner/src/EmbedEventListener.cpp183
-rw-r--r--embed/xulrunner/src/EmbedEventListener.h102
-rw-r--r--embed/xulrunner/src/EmbedProgress.cpp224
-rw-r--r--embed/xulrunner/src/EmbedProgress.h63
-rw-r--r--embed/xulrunner/src/EmbedStream.cpp311
-rw-r--r--embed/xulrunner/src/EmbedStream.h79
-rw-r--r--embed/xulrunner/src/EmbedWindow.cpp467
-rw-r--r--embed/xulrunner/src/EmbedWindow.h97
-rw-r--r--embed/xulrunner/src/EmbedWindowCreator.cpp108
-rw-r--r--embed/xulrunner/src/EmbedWindowCreator.h51
-rw-r--r--embed/xulrunner/src/GeckoBrowser.cpp676
-rw-r--r--embed/xulrunner/src/GeckoBrowser.h159
-rw-r--r--embed/xulrunner/src/GeckoPromptService.cpp891
-rw-r--r--embed/xulrunner/src/GeckoPromptService.h53
-rw-r--r--embed/xulrunner/src/GeckoSingle.cpp122
-rw-r--r--embed/xulrunner/src/GeckoSingle.h97
-rw-r--r--embed/xulrunner/src/GeckoUtils.cpp87
-rw-r--r--embed/xulrunner/src/GeckoUtils.h34
-rw-r--r--embed/xulrunner/src/Makefile.am167
-rw-r--r--embed/xulrunner/src/gecko-dom-event-internal.h28
-rw-r--r--embed/xulrunner/src/gecko-dom-event-private.h38
-rw-r--r--embed/xulrunner/src/gecko-dom-event.cpp78
-rw-r--r--embed/xulrunner/src/gecko-dom-event.h40
-rw-r--r--embed/xulrunner/src/gecko-embed-marshal.list10
-rw-r--r--embed/xulrunner/src/gecko-embed-private.h54
-rw-r--r--embed/xulrunner/src/gecko-embed-signals.h82
-rw-r--r--embed/xulrunner/src/gecko-embed-single-private.h59
-rw-r--r--embed/xulrunner/src/gecko-embed-single.cpp182
-rw-r--r--embed/xulrunner/src/gecko-embed-single.h88
-rw-r--r--embed/xulrunner/src/gecko-embed-types.h118
-rw-r--r--embed/xulrunner/src/gecko-embed.cpp1029
-rw-r--r--embed/xulrunner/src/gecko-embed.h151
-rw-r--r--embed/xulrunner/src/gecko-init-internal.h30
-rw-r--r--embed/xulrunner/src/gecko-init-private.h33
-rw-r--r--embed/xulrunner/src/gecko-init.cpp392
-rw-r--r--embed/xulrunner/src/gecko-init.h35
-rw-r--r--embed/xulrunner/tests/Makefile.am35
-rw-r--r--embed/xulrunner/tests/TestGtkEmbedNotebook.cpp49
-rw-r--r--embed/xulrunner/tests/testgeckoembed.cpp1145
141 files changed, 30405 insertions, 0 deletions
diff --git a/embed/xulrunner/AUTHORS b/embed/xulrunner/AUTHORS
new file mode 100644
index 000000000..7b35d3e1d
--- /dev/null
+++ b/embed/xulrunner/AUTHORS
@@ -0,0 +1,2 @@
+The code was originally taken from mozilla's gtkmozembed
+code. \ No newline at end of file
diff --git a/embed/xulrunner/COPYRIGHT b/embed/xulrunner/COPYRIGHT
new file mode 100644
index 000000000..a4516955f
--- /dev/null
+++ b/embed/xulrunner/COPYRIGHT
@@ -0,0 +1,3 @@
+This library is available under the terms of the
+GNU Lesser General Public Licence, either version 2.1, or
+(at your option) any later version.
diff --git a/embed/xulrunner/ChangeLog b/embed/xulrunner/ChangeLog
new file mode 100644
index 000000000..234c62134
--- /dev/null
+++ b/embed/xulrunner/ChangeLog
@@ -0,0 +1,545 @@
+2006-10-13 Jean-François Rameau <jframeau@cvs.gnome.org>
+
+ * src/Makefile.am:
+ * tests/testgeckoembed.cpp:
+
+ Fix type-builtin part. Fix missing include in testgeckoembed.cpp.
+
+2006-10-08 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/Makefile.am:
+
+ Fix a bug in the last commit.
+
+2006-10-08 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/Makefile.am:
+
+ Make the type builtins value types not global.
+
+2006-09-17 Christian Persch <chpe@cvs.gnome.org>
+
+ * Makefile.am:
+ * configure.ac:
+ * data/Makefile.am:
+ * data/gnome-gecko-embed.pc.in:
+ * m4/gecko.m4:
+
+ Add pkg-config file.
+
+2006-09-06 Christian Persch <chpe@cvs.gnome.org>
+
+ * *.c *.cpp:
+
+ Remove some unnecessary static data.
+
+2006-08-22 Christian Persch <chpe@cvs.gnome.org>
+
+ * configure.ac:
+ * src/EmbedProgress.cpp:
+ * src/Makefile.am:
+ * src/gecko-embed-single.h:
+ R src/gecko-embed-types.c:
+ * src/gecko-embed-types.h:
+ * src/gecko-embed.cpp:
+ * src/gecko-embed.h:
+
+ Autogenerate the type builtins.
+
+2006-08-22 Christian Persch <chpe@cvs.gnome.org>
+
+ A src/AutoWindowModalState.cpp:
+ A src/AutoWindowModalState.h:
+ * src/GeckoPromptService.cpp:
+ * src/Makefile.am:
+
+ Sync with Epiphany.
+
+2006-08-22 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/AutoJSContextStack.cpp:
+ * src/EmbedContentListener.cpp:
+ * src/EmbedEventListener.cpp:
+ * src/EmbedProgress.cpp:
+ * src/EmbedWindowCreator.cpp:
+ * src/GeckoBrowser.cpp:
+ * src/GeckoPromptService.cpp:
+ * src/GeckoSingle.cpp:
+ * src/GeckoUtils.cpp:
+ * src/gecko-dom-event.cpp:
+ * src/gecko-embed-single.cpp:
+ * src/gecko-embed-types.c:
+ * src/gecko-embed.cpp:
+ * src/gecko-init.cpp:
+ * src/nsEmbedAPI.cpp:
+
+ Include config.h unconditionally.
+
+2006-08-22 Christian Persch <chpe@cvs.gnome.org>
+
+ R COPYING:
+ A COPYING.LESSER:
+ R COPYING.MPL:
+ * COPYRIGHT:
+ * Makefile.am:
+ * configure.ac:
+ R src/EmbedComponents.cpp.in:
+ * src/EmbedContentListener.cpp:
+ * src/EmbedContentListener.h:
+ * src/EmbedEventListener.cpp:
+ * src/EmbedEventListener.h:
+ * src/EmbedProgress.cpp:
+ * src/EmbedProgress.h:
+ * src/EmbedStream.cpp:
+ * src/EmbedStream.h:
+ * src/EmbedWindow.cpp:
+ * src/EmbedWindow.h:
+ * src/EmbedWindowCreator.cpp:
+ * src/EmbedWindowCreator.h:
+ * src/GeckoBrowser.cpp:
+ * src/GeckoBrowser.h:
+ * src/GeckoSingle.cpp:
+ * src/GeckoSingle.h:
+ * src/gecko-embed-private.h:
+ * src/gecko-embed-signals.h:
+ * src/gecko-embed-single-private.h:
+ * src/gecko-embed-single.cpp:
+ * src/gecko-embed-single.h:
+ * src/gecko-embed-types.c:
+ * src/gecko-embed-types.h:
+ * src/gecko-embed.cpp:
+ * src/gecko-embed.h:
+ * src/gecko-init.cpp:
+ * src/nsEmbedAPI.cpp:
+ * src/nsProfileDirServiceProvider.cpp:
+ * src/nsProfileDirServiceProvider2.cpp:
+ * tests/testgeckoembed.cpp:
+
+ Cleanup and exercise relicence clause to make this LGPL 2.1+ only.
+
+2006-07-18 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/GeckoPromptService.cpp:
+
+ Force label wrapping.
+
+2006-04-01 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/GeckoPromptService.cpp:
+
+ Fix crash when cancelling the prompt before the timeout has run.
+
+2006-03-21 Christian Persch <chpe@cvs.gnome.org>
+
+ * tests/testgeckoembed.cpp:
+
+ Add handler for context menu signal.
+
+2006-03-21 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/gecko-embed.cpp:
+
+ Fix focus signal connection.
+
+2006-03-21 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/gecko-embed.cpp:
+
+ Fix typo.
+
+2006-03-21 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/Makefile.am:
+ A src/gecko-dom-event.h:
+ A src/gecko-dom-event-internal.h:
+ A src/gecko-dom-event-private.h:
+ A src/gecko-dom-event.cpp:
+ * src/EmbedEventListener.cpp:
+ * src/EmbedEventListener.h:
+ * src/GeckoBrowser.cpp:
+ * src/gecko-embed-marshal.list:
+ * src/gecko-embed-signals.h:
+ * src/gecko-embed.cpp:
+ * src/gecko-embed.h:
+ * tests/testgeckoembed.cpp:
+
+ Rework the DOM signals.
+ Add context menu signal.
+
+2006-03-21 Christian Persch <chpe@cvs.gnome.org>
+
+ R src/gecko-embed-marshal.c:
+ R src/gecko-embed-marshal.h:
+
+ Remove autogenerated files from cvs.
+
+2006-03-17 Xan Lopez <xan@gnome.org>
+
+ * src/GeckoSingle.cpp:
+ * src/Makefile.am:
+ * src/gecko-init-private.h:
+ * src/gecko-init.cpp:
+ * src/gecko-init.h:
+ * tests/testgeckoembed.cpp:
+
+ Rework headers.
+
+2006-03-17 Xan Lopez <xan@gnome.org>
+
+ * src/GeckoSingle.cpp:
+ * src/GeckoSingle.h:
+ * src/Makefile.am:
+ * src/gecko-embed-single.cpp:
+ * src/gecko-embed-single.h:
+ * src/gecko-init-private.h:
+ * src/gecko-init.cpp:
+ * src/gecko-init.h:
+
+ Moved init/shutdown logic to gecko-init
+
+ * tests/testgeckoembed.cpp:
+
+ Change test to use new functions
+
+2006-03-15 Xan Lopez <xan@gnome.org>
+
+ * bindings/python/test.py:
+
+ Update.
+
+2006-03-15 Xan Lopez <xan@gnome.org>
+
+ * bindings/python/gnomegeckoembed.defs:
+ * src/gecko-embed-types.h:
+
+ Fix the flags/enum thing properly.
+
+2006-03-15 Xan Lopez <xan@gnome.org>
+
+ * m4/python.m4:
+
+ Forgot.
+
+2006-03-15 Xan Lopez <xan@gnome.org>
+
+ * Makefile.am:
+ * bindings/Makefile.am:
+ * bindings/python/Makefile.am:
+ * bindings/python/gnomegeckoembed.defs:
+ * bindings/python/gnomegeckoembed.override:
+ * bindings/python/gnomegeckoembedmodule.c: (initgnomegeckoembed):
+ * bindings/python/test.py:
+ * configure.ac:
+
+ Python bindings.
+
+ * src/GeckoBrowser.cpp:
+
+ Fix typo.
+
+ * src/gecko-embed-types.h:
+
+ s/GECKO_TYPE_EMBED_STATUS_ENUM/GECKO_TYPE_EMBED_STATUS_FLAGS/
+
+2006-03-14 Jean-François Rameau <jframeau@cvs.gnome.org>
+
+ * autogen.sh:
+ * src/GeckoSingle.cpp:
+
+ Fix some typos.
+
+2006-03-13 Christian Persch <chpe@cvs.gnome.org>
+
+ R src/EmbedPrompter.cpp:
+ R src/EmbedPrompter.h:
+ R src/GtkPromptService.cpp:
+ R src/GtkPromptService.h:
+ A src/AutoJSContextStack.cpp:
+ A src/AutoJSContextStack.h:
+ A src/GeckoPromptService.cpp:
+ A src/GeckoPromptService.h:
+ * src/EmbedWindow.cpp:
+ * src/GeckoBrowser.cpp:
+ * src/GeckoSingle.cpp:
+ * src/GeckoUtils.cpp:
+ * src/GeckoUtils.h:
+ * src/Makefile.am:
+
+ Import prompt service implementation from Epiphany.
+
+2004-03-13 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/gecko-embed.cpp:
+
+ Fix signal declarations to include RUN_LAST.
+
+2006-03-13 Xan Lopez <xan@gnome.org>
+
+ * src/EmbedEventListener.cpp:
+
+ Merge https://bugzilla.mozilla.org/show_bug.cgi?id=306839
+
+2004-03-13 Christian Persch <chpe@cvs.gnome.org>
+
+ * Makefile.am:
+
+ Add ACLOCAL_AMFLAGS.
+
+2004-03-13 Christian Persch <chpe@cvs.gnome.org>
+
+ * configure.ac:
+
+ We don't want to support gecko 1.7 or non-toolkit geckos.
+
+2006-03-13 Xan Lopez <xan@gnome.org>
+
+ * src/gecko-embed-types.c: (gecko_embed_progress_flags_get_type):
+ * src/gecko-embed-types.h:
+
+ Merge https://bugzilla.mozilla.org/show_bug.cgi?id=306550
+
+2006-03-13 Xan Lopez <xan@gnome.org>
+
+ * src/GeckoBrowser.cpp:
+ * src/GeckoSingle.h:
+ * src/gecko-embed.cpp:
+
+ Merge https://bugzilla.mozilla.org/show_bug.cgi?id=210373
+
+2006-03-13 Xan Lopez <xan@gnome.org>
+
+ * src/GeckoBrowser.h:
+ * src/GeckoSingle.cpp:
+ * src/GeckoSingle.h:
+ * src/Makefile.am:
+
+ Merge https://bugzilla.mozilla.org/show_bug.cgi?id=275463
+
+2006-03-13 Xan Lopez <xan@gnome.org>
+
+ * src/GeckoBrowser.cpp:
+ * src/GeckoBrowser.h:
+ * src/gecko-embed.cpp:
+
+ Ahem, back off #97580.
+
+2006-03-13 Xan Lopez <xan@gnome.org>
+
+ * src/gecko-embed.cpp:
+
+ Merge http://bonsai.mozilla.org/cvsview2.cgi?diff_mode=context&whitespace_mode=show&subdir=mozilla/embedding/browser/gtk/src&command=DIFF_FRAMESET&file=gtkmozembed2.cpp&rev1=1.42&rev2=1.43&root=/cvsroot
+
+2006-03-13 Xan Lopez <xan@gnome.org>
+
+ * src/EmbedContentListener.cpp:
+
+ Merge http://bonsai.mozilla.org/cvsview2.cgi?diff_mode=context&whitespace_mode=show&subdir=mozilla/embedding/browser/gtk/src&command=DIFF_FRAMESET&file=EmbedContentListener.cpp&rev1=1.17&rev2=1.18&root=/cvsroot
+
+2006-03-13 Xan Lopez <xan@gnome.org>
+
+ * src/GeckoBrowser.cpp:
+ * src/GeckoBrowser.h:
+ * src/gecko-embed.cpp:
+
+ Merge https://bugzilla.mozilla.org/show_bug.cgi?id=97580
+
+2006-03-13 Xan Lopez <xan@gnome.org>
+
+ * src/GeckoSingle.cpp:
+
+ Merge https://bugzilla.mozilla.org/show_bug.cgi?id=242024
+
+2006-03-13 Xan Lopez <xan@gnome.org>
+
+ * src/EmbedWindow.cpp:
+
+ Merge https://bugzilla.mozilla.org/show_bug.cgi?id=238052
+
+2006-03-13 Xan Lopez <xan@gnome.org>
+
+ * configure.ac:
+
+ Fix typo.
+
+ * src/GeckoBrowser.cpp:
+
+ Merge https://bugzilla.mozilla.org/show_bug.cgi?id=276482
+
+2004-09-25 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/GeckoBrowser.cpp:
+ * src/GeckoSingle.cpp:
+ * src/gecko-embed-single.cpp:
+ * tests/testgeckoembed.cpp:
+
+ Make testgeckoembed link.
+
+2004-09-24 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/EmbedProgress.cpp:
+ * src/GeckoBrowser.cpp:
+ * src/GeckoSingle.cpp:
+ * src/GeckoSingle.h:
+ * src/gecko-embed-single.cpp:
+ * src/gecko-embed.cpp:
+
+ Fix startup.
+
+2004-09-24 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/gecko-embed.cpp:
+
+ Last GtkSignal bits ported to gobject.
+
+2004-09-24 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/EmbedEventListener.cpp:
+ * src/EmbedProgress.cpp:
+ * src/EmbedWindow.cpp:
+ * src/EmbedWindowCreator.cpp:
+ * src/GeckoBrowser.h:
+ * src/GeckoSingle.cpp:
+ * src/gecko-embed-signals.h:
+ * src/gecko-embed.cpp:
+ * src/gecko-embed.h:
+
+ More gobject porting.
+
+2004-09-24 Christian Persch <chpe@cvs.gnome.org>
+
+ * tests/Makefile.am:
+ * tests/TestGtkEmbed.cpp:
+ * tests/testgeckoembed.cpp:
+
+ Started to port testgeckoembed to GeckoEmbed.
+
+2004-09-24 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/EmbedWindowCreator.cpp:
+
+ Ported to gobject.
+
+2004-09-24 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/EmbedPrompter.cpp:
+ * src/EmbedWindow.cpp:
+
+ Ported to gobject.
+
+2004-09-24 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/EmbedProgress.cpp:
+
+ Ported to gobject.
+
+ * src/gecko-embed-marshal.list:
+ * src/gecko-embed.cpp:
+
+ Fix a signal.
+
+2004-09-24 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/EmbedContentListener.cpp:
+ * src/EmbedEventListener.cpp:
+
+ Ported to gobject.
+
+2004-09-24 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/EmbedContentListener.cpp:
+ * src/EmbedContentListener.h:
+ * src/EmbedEventListener.cpp:
+ * src/EmbedEventListener.h:
+ * src/EmbedPrivate.cpp:
+ * src/EmbedPrivate.h:
+ * src/EmbedProgress.cpp:
+ * src/EmbedProgress.h:
+ * src/EmbedWindow.cpp:
+ * src/EmbedWindow.h:
+ * src/EmbedWindowCreator.cpp:
+ * src/GeckoBrowser.cpp:
+ * src/GeckoBrowser.h:
+ * src/GeckoSingle.cpp:
+ * src/GeckoSingle.h:
+ * src/Makefile.am:
+ * src/gecko-embed-marshal.list:
+ * src/gecko-embed-marshalers.list:
+ * src/gecko-embed-private.h:
+ * src/gecko-embed-signals.h:
+ * src/gecko-embed-single-private.h:
+ * src/gecko-embed-single.cpp:
+ * src/gecko-embed-types.c: (gecko_embed_progress_flags_get_type),
+ (gecko_embed_status_enums_get_type),
+ (gecko_embed_reload_flags_get_type),
+ (gecko_embed_chrome_flags_get_type):
+ * src/gecko-embed-types.h:
+ * src/gecko-embed.cpp:
+ * src/gecko-embed.h:
+ * src/gtkmozembed.h:
+ * src/gtkmozembed2.cpp:
+ * src/gtkmozembed_internal.h:
+ * src/gtkmozembedmarshal.list:
+ * src/gtkmozembedprivate.h:
+
+ Renamed GtkMozEmbed to GeckoEmbed, EmbedPrivate to GeckoBrowser and split
+ GeckoBrowser into per-embed and global things (-> GeckoSingle).
+ First round of making things use gobject instead of gtkobject.
+
+2004-09-23 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/Makefile.am:
+ * src/gtkmozembedmarshal.c:
+ * src/gtkmozembedmarshal.h:
+
+ Make marshalers autogenerate from list.
+
+2004-09-23 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/EmbedPrivate.cpp:
+ * src/EmbedWindow.cpp:
+ * src/gtkmozembed2.cpp:
+ * tests/TestGtkEmbed.cpp:
+ * tests/TestGtkEmbedChild.cpp:
+ * tests/TestGtkEmbedMDI.cpp:
+ * tests/TestGtkEmbedSocket.cpp:
+
+ Remove all #ifdef MOZ_WIDGET_GTK code, and remove the
+ checks for MOZ_WIDGET_GTK2.
+
+2004-09-23 Christian Persch <chpe@cvs.gnome.org>
+
+ * src/EmbedPrivate.cpp:
+ * src/Makefile.am:
+ * tests/Makefile.am:
+ * tests/TestGtkEmbed.cpp:
+
+ Make it link and run.
+
+2004-09-21 Christian Persch <chpe@cvs.gnome.org>
+
+ * data/gnome-gecko-embed-0.0.pc.in:
+ * src/EmbedContentListener.cpp:
+ * src/EmbedPrivate.cpp:
+ * src/EmbedPrivate.h:
+ * src/EmbedProgress.cpp:
+ * src/EmbedProgress.h:
+ * src/EmbedPrompter.cpp:
+ * src/EmbedPrompter.h:
+ * src/EmbedWindow.cpp:
+ * src/EmbedWindow.h:
+ * src/GtkPromptService.cpp:
+ * src/GtkPromptService.h:
+ * src/Makefile.am:
+ * src/gtkmozembed2.cpp:
+
+ Incorporate latest patch [http://bugzilla.mozilla.org/attachment.cgi?id=148650&action=view]
+ from bug [http://bugzilla.mozilla.org/show_bug.cgi?id=205425].
+
+2004-09-21 Christian Persch <chpe@cvs.gnome.org>
+
+ * TODO:
+ * autogen.sh:
+ * configure.ac:
+ * src/Makefile.am:
+
+ Make it pass autogen.
diff --git a/embed/xulrunner/HACKING b/embed/xulrunner/HACKING
new file mode 100644
index 000000000..b93d7ae64
--- /dev/null
+++ b/embed/xulrunner/HACKING
@@ -0,0 +1,10 @@
+Do NOT commit to this module without permission from
+chpe@gnome.org .
+
+Please send patches either to chpe@gnome.org or for discussion to
+epiphany-list@gnome.org.
+
+Code style is mozilla code style, that is 2-spaces for indentation, and
+curly brackets are on a the same line.
+
+All files have to be encoded in UTF-8.
diff --git a/embed/xulrunner/MAINTAINERS b/embed/xulrunner/MAINTAINERS
new file mode 100644
index 000000000..7e15500c2
--- /dev/null
+++ b/embed/xulrunner/MAINTAINERS
@@ -0,0 +1,2 @@
+Email: chpe@gnome.org
+Email: xan@gnome.org
diff --git a/embed/xulrunner/Makefile.am b/embed/xulrunner/Makefile.am
new file mode 100644
index 000000000..1a6185567
--- /dev/null
+++ b/embed/xulrunner/Makefile.am
@@ -0,0 +1,9 @@
+SUBDIRS = src data bindings tests
+
+NULL =
+
+EXTRA_DIST = \
+ README \
+ TODO \
+ COPYRIGHT \
+ $(NULL)
diff --git a/embed/xulrunner/NEWS b/embed/xulrunner/NEWS
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/embed/xulrunner/NEWS
diff --git a/embed/xulrunner/PLAN b/embed/xulrunner/PLAN
new file mode 100644
index 000000000..50d0e9427
--- /dev/null
+++ b/embed/xulrunner/PLAN
@@ -0,0 +1,26 @@
+The plan is to fix the things which suck in gtkmozembed and some of
+which require direct access to the embedding layer to be fixed.
+
+Note that the following plans are not set in stone.
+
+- lifecycle:
+ Move from the push_startup/pop_startup lifecycle management to explicit
+ init/shutdown.
+- dom events:
+ Make the DOM events signals actually useful by implementing a DOM context
+ class accessible from C, where the context is only calculated on demand
+ (since DOM signals can be emitted frequently and getting context is slow)
+- gtk-like tooltips:
+ Make tooltips follow mouse (like in evince), not time out, and and make sure
+ they don't fall off the side of the screen
+- printing:
+ Integrate with gtk+ 2.10 printing out-of-the-box; atm every application
+ codes its own libgnomeprint ps-to-printer support.
+- more gobject-like:
+ Make use of gobject properties instead of signals (à la EphyTab)
+- find:
+ Copy EphyEmbedFind.
+- prefs:
+ Provide access to mozilla prefs from C (like mozilla-notifiers.h in epiphany/embed/mozilla/)
+ and map common gconf prefs to moz prefs automatically (like mozilla-notifiers.cpp).
+ That way we can also share the font prefs between epiphany, yelp and devhelp.
diff --git a/embed/xulrunner/README b/embed/xulrunner/README
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/embed/xulrunner/README
diff --git a/embed/xulrunner/STATUS b/embed/xulrunner/STATUS
new file mode 100644
index 000000000..7732c1479
--- /dev/null
+++ b/embed/xulrunner/STATUS
@@ -0,0 +1,2 @@
+Taken from gtkmozembed trunk on 2004-09-21
+
diff --git a/embed/xulrunner/TODO b/embed/xulrunner/TODO
new file mode 100644
index 000000000..e8bb8e81b
--- /dev/null
+++ b/embed/xulrunner/TODO
@@ -0,0 +1 @@
+- Fix tooltip direction: on RTL the tooltip should be RTL too! (see https://bugzilla.mozilla.org/show_bug.cgi?id=91312)
diff --git a/embed/xulrunner/bindings/Makefile.am b/embed/xulrunner/bindings/Makefile.am
new file mode 100644
index 000000000..0f4745056
--- /dev/null
+++ b/embed/xulrunner/bindings/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS =
+
+if ENABLE_PYTHON
+SUBDIRS += python
+endif
diff --git a/embed/xulrunner/bindings/python/Makefile.am b/embed/xulrunner/bindings/python/Makefile.am
new file mode 100644
index 000000000..68ed1efe9
--- /dev/null
+++ b/embed/xulrunner/bindings/python/Makefile.am
@@ -0,0 +1,63 @@
+defsdir = $(datadir)/pygtk/2.0/defs
+defs_DATA = gnomegeckoembed.defs
+
+pkgpythondir = $(pyexecdir)/gtk-2.0
+pkgpyexecdir = $(pyexecdir)/gtk-2.0
+
+# gnomegeckoembed module
+pkgpyexec_LTLIBRARIES = gnomegeckoembed.la
+
+gnomegeckoembed_la_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/embed/gecko/src \
+ -I$(top_builddir)/embed/gecko/src \
+ $(AM_CPPFLAGS)
+
+gnomegeckoembed_la_CFLAGS = \
+ $(GGE_DEPENDENCY_CFLAGS) \
+ $(GECKO_CFLAGS) \
+ $(NO_STRICT_ALIASING_CFLAGS) \
+ $(PYGTK_CFLAGS) \
+ $(PYTHON_CFLAGS) \
+ $(AM_CFLAGS)
+
+gnomegeckoembed_la_LIBADD = \
+ $(top_builddir)/embed/gecko/src/libgnomegeckoembed-0.0.la \
+ $(GECKO_LIBS) \
+ $(PYTHON_LIBS) \
+ $(PYTHON_EXTRA_LIBS) \
+ $(PYGTK_LIBS)
+
+gnomegeckoembed_la_LDFLAGS = \
+ -module -avoid-version \
+ -export-symbols-regex initgnomegeckoembed \
+ -R$(GECKO_HOME) \
+ $(AM_LDFLAGS)
+
+gnomegeckoembed_la_SOURCES = gnomegeckoembedmodule.c
+nodist_gnomegeckoembed_la_SOURCES = gnomegeckoembed.c
+
+gnomegeckoembed.c: gnomegeckoembed.defs gnomegeckoembed.override
+CLEANFILES = gnomegeckoembed.c
+EXTRA_DIST = gnomegeckoembed.override gnomegeckoembed.defs
+
+.defs.c:
+ (cd $(srcdir)\
+ && $(PYGTK_CODEGEN) \
+ --override $*.override \
+ --prefix py$* $*.defs) > gen-$*.c \
+ && cp gen-$*.c $*.c \
+ && rm -f gen-$*.c
+
+BINDING_HEADERS_SRCDIR_IN = \
+ src/gecko-embed.h \
+ src/gecko-embed-single.h \
+ src/gecko-embed-types.h
+
+BINDING_HEADERS_BUILDDIR_IN =
+
+BINDING_HEADERS_SRCDIR := $(addprefix $(top_srcdir)/,$(BINDING_HEADERS_SRCDIR_IN))
+BINDING_HEADERS_BUILDDIR := $(addprefix $(top_builddir)/,$(BINDING_HEADERS_BUILDDIR_IN))
+
+regenerate-python-binding:
+ $(PYGTK_H2DEF) $(sort $(BINDING_HEADERS_SRCDIR) $(BINDING_HEADERS_BUILDDIR)) > gnomegeckoembed.defs.new
diff --git a/embed/xulrunner/bindings/python/gnomegeckoembed.defs b/embed/xulrunner/bindings/python/gnomegeckoembed.defs
new file mode 100644
index 000000000..e3c0f10b5
--- /dev/null
+++ b/embed/xulrunner/bindings/python/gnomegeckoembed.defs
@@ -0,0 +1,294 @@
+;; -*- scheme -*-
+; object definitions ...
+(define-object Embed
+ (in-module "Gecko")
+ (parent "GtkBin")
+ (c-name "GeckoEmbed")
+ (gtype-id "GECKO_TYPE_EMBED")
+)
+
+(define-object EmbedSingle
+ (in-module "Gecko")
+ (parent "GObject")
+ (c-name "GeckoEmbedSingle")
+ (gtype-id "GECKO_TYPE_EMBED_SINGLE")
+)
+
+;; Enumerations and flags ...
+
+(define-enum EmbedProgressFlags
+ (in-module "Gecko")
+ (c-name "GeckoEmbedProgressFlags")
+ (gtype-id "GECKO_TYPE_EMBED_PROGRESS_FLAGS")
+ (values
+ '("start" "GECKO_EMBED_FLAG_START")
+ '("redirecting" "GECKO_EMBED_FLAG_REDIRECTING")
+ '("transferring" "GECKO_EMBED_FLAG_TRANSFERRING")
+ '("negotiating" "GECKO_EMBED_FLAG_NEGOTIATING")
+ '("stop" "GECKO_EMBED_FLAG_STOP")
+ '("is-request" "GECKO_EMBED_FLAG_IS_REQUEST")
+ '("is-document" "GECKO_EMBED_FLAG_IS_DOCUMENT")
+ '("is-network" "GECKO_EMBED_FLAG_IS_NETWORK")
+ '("is-window" "GECKO_EMBED_FLAG_IS_WINDOW")
+ '("restoring" "GECKO_EMBED_FLAG_RESTORING")
+ )
+)
+
+(define-enum EmbedStatusEnum
+ (in-module "Gecko")
+ (c-name "GeckoEmbedStatusEnum")
+ (gtype-id "GECKO_TYPE_EMBED_STATUS_ENUM")
+ (values
+ '("dns" "GECKO_EMBED_STATUS_FAILED_DNS")
+ '("connect" "GECKO_EMBED_STATUS_FAILED_CONNECT")
+ '("timeout" "GECKO_EMBED_STATUS_FAILED_TIMEOUT")
+ '("usercanceled" "GECKO_EMBED_STATUS_FAILED_USERCANCELED")
+ )
+)
+
+(define-enum EmbedReloadFlags
+ (in-module "Gecko")
+ (c-name "GeckoEmbedReloadFlags")
+ (gtype-id "GECKO_TYPE_EMBED_RELOAD_FLAGS")
+ (values
+ '("normal" "GECKO_EMBED_FLAG_RELOADNORMAL")
+ '("bypasscache" "GECKO_EMBED_FLAG_RELOADBYPASSCACHE")
+ '("bypassproxy" "GECKO_EMBED_FLAG_RELOADBYPASSPROXY")
+ '("bypassproxyandcache" "GECKO_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE")
+ '("charsetchange" "GECKO_EMBED_FLAG_RELOADCHARSETCHANGE")
+ )
+)
+
+(define-enum EmbedChromeFlags
+ (in-module "Gecko")
+ (c-name "GeckoEmbedChromeFlags")
+ (gtype-id "GECKO_TYPE_EMBED_CHROME_FLAGS")
+ (values
+ '("defaultchrome" "GECKO_EMBED_FLAG_DEFAULTCHROME")
+ '("windowborderson" "GECKO_EMBED_FLAG_WINDOWBORDERSON")
+ '("windowcloseon" "GECKO_EMBED_FLAG_WINDOWCLOSEON")
+ '("windowresizeon" "GECKO_EMBED_FLAG_WINDOWRESIZEON")
+ '("menubaron" "GECKO_EMBED_FLAG_MENUBARON")
+ '("toolbaron" "GECKO_EMBED_FLAG_TOOLBARON")
+ '("locationbaron" "GECKO_EMBED_FLAG_LOCATIONBARON")
+ '("statusbaron" "GECKO_EMBED_FLAG_STATUSBARON")
+ '("personaltoolbaron" "GECKO_EMBED_FLAG_PERSONALTOOLBARON")
+ '("scrollbarson" "GECKO_EMBED_FLAG_SCROLLBARSON")
+ '("titlebaron" "GECKO_EMBED_FLAG_TITLEBARON")
+ '("extrachromeon" "GECKO_EMBED_FLAG_EXTRACHROMEON")
+ '("allchrome" "GECKO_EMBED_FLAG_ALLCHROME")
+ '("windowraised" "GECKO_EMBED_FLAG_WINDOWRAISED")
+ '("windowlowered" "GECKO_EMBED_FLAG_WINDOWLOWERED")
+ '("centerscreen" "GECKO_EMBED_FLAG_CENTERSCREEN")
+ '("dependent" "GECKO_EMBED_FLAG_DEPENDENT")
+ '("modal" "GECKO_EMBED_FLAG_MODAL")
+ '("openasdialog" "GECKO_EMBED_FLAG_OPENASDIALOG")
+ '("openaschrome" "GECKO_EMBED_FLAG_OPENASCHROME")
+ )
+)
+
+
+;; From ../../src/gecko-embed-single.h
+
+(define-function gecko_embed_single_get_type
+ (c-name "gecko_embed_single_get_type")
+ (return-type "GType")
+)
+
+(define-function gecko_embed_single_get
+ (c-name "gecko_embed_single_get")
+ (return-type "GeckoEmbedSingle*")
+)
+
+(define-function gecko_embed_single_push_startup
+ (c-name "gecko_embed_single_push_startup")
+ (return-type "none")
+)
+
+(define-function gecko_embed_single_pop_startup
+ (c-name "gecko_embed_single_pop_startup")
+ (return-type "none")
+)
+
+(define-function gecko_embed_single_set_comp_path
+ (c-name "gecko_embed_single_set_comp_path")
+ (return-type "none")
+ (parameters
+ '("const-char*" "aPath")
+ )
+)
+
+(define-function gecko_embed_single_set_profile_path
+ (c-name "gecko_embed_single_set_profile_path")
+ (return-type "none")
+ (parameters
+ '("const-char*" "aDir")
+ '("const-char*" "aName")
+ )
+)
+
+
+
+;; From ../../src/gecko-embed-types.h
+
+(define-function gecko_embed_progress_flags_get_type
+ (c-name "gecko_embed_progress_flags_get_type")
+ (return-type "GType")
+)
+
+(define-function gecko_embed_status_enum_get_type
+ (c-name "gecko_embed_status_enum_get_type")
+ (return-type "GType")
+)
+
+(define-function gecko_embed_reload_flags_get_type
+ (c-name "gecko_embed_reload_flags_get_type")
+ (return-type "GType")
+)
+
+(define-function gecko_embed_chrome_flags_get_type
+ (c-name "gecko_embed_chrome_flags_get_type")
+ (return-type "GType")
+)
+
+
+
+;; From ../../src/gecko-embed.h
+
+(define-function gecko_embed_get_type
+ (c-name "gecko_embed_get_type")
+ (return-type "GType")
+)
+
+(define-function gecko_embed_new
+ (c-name "gecko_embed_new")
+ (is-constructor-of "GeckoEmbed")
+ (return-type "GtkWidget*")
+)
+
+(define-method load_url
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_load_url")
+ (return-type "none")
+ (parameters
+ '("const-char*" "url")
+ )
+)
+
+(define-method stop_load
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_stop_load")
+ (return-type "none")
+)
+
+(define-method can_go_back
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_can_go_back")
+ (return-type "gboolean")
+)
+
+(define-method can_go_forward
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_can_go_forward")
+ (return-type "gboolean")
+)
+
+(define-method go_back
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_go_back")
+ (return-type "none")
+)
+
+(define-method go_forward
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_go_forward")
+ (return-type "none")
+)
+
+(define-method render_data
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_render_data")
+ (return-type "none")
+ (parameters
+ '("const-char*" "data")
+ '("guint32" "len")
+ '("const-char*" "base_uri")
+ '("const-char*" "mime_type")
+ )
+)
+
+(define-method open_stream
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_open_stream")
+ (return-type "none")
+ (parameters
+ '("const-char*" "base_uri")
+ '("const-char*" "mime_type")
+ )
+)
+
+(define-method append_data
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_append_data")
+ (return-type "none")
+ (parameters
+ '("const-char*" "data")
+ '("guint32" "len")
+ )
+)
+
+(define-method close_stream
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_close_stream")
+ (return-type "none")
+)
+
+(define-method get_link_message
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_get_link_message")
+ (return-type "char*")
+)
+
+(define-method get_js_status
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_get_js_status")
+ (return-type "char*")
+)
+
+(define-method get_title
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_get_title")
+ (return-type "char*")
+)
+
+(define-method get_location
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_get_location")
+ (return-type "char*")
+)
+
+(define-method reload
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_reload")
+ (return-type "none")
+ (parameters
+ '("gint32" "flags")
+ )
+)
+
+(define-method set_chrome_mask
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_set_chrome_mask")
+ (return-type "none")
+ (parameters
+ '("guint32" "flags")
+ )
+)
+
+(define-method get_chrome_mask
+ (of-object "GeckoEmbed")
+ (c-name "gecko_embed_get_chrome_mask")
+ (return-type "guint32")
+)
+
+
diff --git a/embed/xulrunner/bindings/python/gnomegeckoembed.override b/embed/xulrunner/bindings/python/gnomegeckoembed.override
new file mode 100644
index 000000000..e40fb9afe
--- /dev/null
+++ b/embed/xulrunner/bindings/python/gnomegeckoembed.override
@@ -0,0 +1,19 @@
+%%
+headers
+#include <Python.h>
+
+#include "pygobject.h"
+#include "gecko-embed.h"
+#include "gecko-embed-single.h"
+
+%%
+modulename gnomegeckoembed
+%%
+import gobject.GObject as PyGObject_Type
+import gtk.Object as PyGtkObject_Type
+import gtk.Bin as PyGtkBin_Type
+%%
+ignore-glob
+ *_get_type
+ _*
+%%
diff --git a/embed/xulrunner/bindings/python/gnomegeckoembedmodule.c b/embed/xulrunner/bindings/python/gnomegeckoembedmodule.c
new file mode 100644
index 000000000..f7786fa17
--- /dev/null
+++ b/embed/xulrunner/bindings/python/gnomegeckoembedmodule.c
@@ -0,0 +1,29 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* include this first, before NO_IMPORT_PYGOBJECT is defined */
+#include <pygobject.h>
+
+void pygtkmozembed_register_classes (PyObject *d);
+void pygtkmozembed_add_constants(PyObject *module, const gchar *strip_prefix);
+
+extern PyMethodDef pygnomegeckoembed_functions[];
+
+DL_EXPORT(void)
+initgnomegeckoembed(void)
+{
+ PyObject *m, *d;
+
+ init_pygobject ();
+
+ m = Py_InitModule ("gnomegeckoembed", pygnomegeckoembed_functions);
+ d = PyModule_GetDict (m);
+
+ pygnomegeckoembed_register_classes (d);
+ /*pygnomegeckoembed_add_constants(m, "GNOME_GECKO_EMBED_");*/
+
+ if (PyErr_Occurred ()) {
+ Py_FatalError ("can't initialise module gnomegeckoembed");
+ }
+}
diff --git a/embed/xulrunner/bindings/python/test.py b/embed/xulrunner/bindings/python/test.py
new file mode 100644
index 000000000..d06278e5f
--- /dev/null
+++ b/embed/xulrunner/bindings/python/test.py
@@ -0,0 +1,32 @@
+#! /usr/bin/python
+import pygtk
+pygtk.require("2.0")
+import gtk
+import gnomegeckoembed
+import os
+
+class Base:
+ def destroy(self, widget, data=None):
+ gtk.main_quit()
+
+ def __init__(self):
+ gnomegeckoembed.gecko_embed_single_set_comp_path("/usr/lib/firefox")
+ gnomegeckoembed.gecko_embed_single_push_startup()
+ self.browser = gnomegeckoembed.Embed()
+ self.browser.load_url("www.gnome.org")
+
+ self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ self.window.connect("destroy", self.destroy)
+ self.window.set_default_size(800, 600)
+ self.window.add(self.browser)
+ self.browser.show()
+ self.window.show()
+
+ def main(self):
+ gtk.main()
+
+print __name__
+if __name__ == "__main__":
+ base = Base()
+ base.main()
+
diff --git a/embed/xulrunner/data/Makefile.am b/embed/xulrunner/data/Makefile.am
new file mode 100644
index 000000000..3363f76b4
--- /dev/null
+++ b/embed/xulrunner/data/Makefile.am
@@ -0,0 +1,3 @@
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = gnome-gecko-embed-$(GGE_API_VERSION).pc
+
diff --git a/embed/xulrunner/data/gnome-gecko-embed.pc.in b/embed/xulrunner/data/gnome-gecko-embed.pc.in
new file mode 100644
index 000000000..c9887651b
--- /dev/null
+++ b/embed/xulrunner/data/gnome-gecko-embed.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: GNOME Gecko Embed Library
+Description: GNOME Gecko Embed Library
+Version: @GGE_VERSION@
+Requires: gtk+-2.0, @GECKO@-xpcom
+Libs: -L${libdir}
+Cflags: -I${includedir}
diff --git a/embed/xulrunner/embed/AutoJSContextStack.cpp b/embed/xulrunner/embed/AutoJSContextStack.cpp
new file mode 100644
index 000000000..97fa84f33
--- /dev/null
+++ b/embed/xulrunner/embed/AutoJSContextStack.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <nsServiceManagerUtils.h>
+
+#include "AutoJSContextStack.h"
+
+AutoJSContextStack::~AutoJSContextStack()
+{
+ if (mStack)
+ {
+ JSContext* cx;
+ mStack->Pop (&cx);
+
+ NS_ASSERTION(cx == nsnull, "We pushed a null context but popped a non-null context!?");
+ }
+}
+
+nsresult
+AutoJSContextStack::Init()
+{
+ nsresult rv;
+ mStack = do_GetService ("@mozilla.org/js/xpc/ContextStack;1", &rv);
+ if (NS_FAILED (rv)) return rv;
+
+ return mStack->Push (nsnull);
+}
diff --git a/embed/xulrunner/embed/AutoJSContextStack.h b/embed/xulrunner/embed/AutoJSContextStack.h
new file mode 100644
index 000000000..0db423a64
--- /dev/null
+++ b/embed/xulrunner/embed/AutoJSContextStack.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef AUTO_JSCONTEXTSTACK_H
+#define AUTO_JSCONTEXTSTACK_H
+
+struct JSContext;
+
+#include <nsCOMPtr.h>
+#include <nsIJSContextStack.h>
+
+class AutoJSContextStack
+{
+ public:
+ AutoJSContextStack () { }
+ ~AutoJSContextStack ();
+
+ nsresult Init ();
+
+ private:
+ nsCOMPtr<nsIJSContextStack> mStack;
+};
+
+#endif
diff --git a/embed/xulrunner/embed/AutoWindowModalState.cpp b/embed/xulrunner/embed/AutoWindowModalState.cpp
new file mode 100644
index 000000000..0ff11e4ab
--- /dev/null
+++ b/embed/xulrunner/embed/AutoWindowModalState.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include "AutoWindowModalState.h"
+
+AutoWindowModalState::AutoWindowModalState (nsIDOMWindow *aWindow)
+{
+#ifdef HAVE_GECKO_1_8_1
+ if (aWindow) {
+ mWindow = do_QueryInterface (aWindow);
+ NS_ASSERTION (mWindow, "Should have a window here!");
+ }
+
+ if (mWindow) {
+#ifdef HAVE_GECKO_1_9
+ mWindow->EnterModalState ();
+#else
+ nsCOMPtr<nsPIDOMWindow_MOZILLA_1_8_BRANCH> window (do_QueryInterface (mWindow));
+ NS_ENSURE_TRUE (window, );
+
+ window->EnterModalState ();
+#endif /* HAVE_GECKO_1_9 */
+ }
+#endif /* HAVE_GECKO_1_8_1 */
+}
+
+AutoWindowModalState::~AutoWindowModalState()
+{
+#ifdef HAVE_GECKO_1_8_1
+ if (mWindow) {
+#ifdef HAVE_GECKO_1_9
+ mWindow->LeaveModalState ();
+#else
+ nsCOMPtr<nsPIDOMWindow_MOZILLA_1_8_BRANCH> window (do_QueryInterface (mWindow));
+ NS_ENSURE_TRUE (window, );
+
+ window->LeaveModalState ();
+#endif /* HAVE_GECKO_1_9 */
+ }
+#endif /* HAVE_GECKO_1_8_1 */
+}
diff --git a/embed/xulrunner/embed/AutoWindowModalState.h b/embed/xulrunner/embed/AutoWindowModalState.h
new file mode 100644
index 000000000..557865799
--- /dev/null
+++ b/embed/xulrunner/embed/AutoWindowModalState.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef AUTO_WINDOWMODALSTATE_H
+#define AUTO_WINDOWMODALSTATE_H
+
+#include <nsCOMPtr.h>
+#include <nsPIDOMWindow.h>
+
+class AutoWindowModalState
+{
+ public:
+ AutoWindowModalState (nsIDOMWindow *);
+ ~AutoWindowModalState ();
+
+ private:
+
+ nsCOMPtr<nsPIDOMWindow> mWindow;
+};
+
+#endif
diff --git a/embed/xulrunner/embed/ContentHandler.cpp b/embed/xulrunner/embed/ContentHandler.cpp
new file mode 100644
index 000000000..0510aa3f1
--- /dev/null
+++ b/embed/xulrunner/embed/ContentHandler.cpp
@@ -0,0 +1,479 @@
+/*
+ * Copyright © 2001 Philip Langdale
+ * Copyright © 2003 Marco Pesenti Gritti
+ * Copyright © 2003 Xan Lopez
+ * Copyright © 2004 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkstock.h>
+#include <libgnomevfs/gnome-vfs-mime.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+
+#include <nsStringAPI.h>
+
+#include <nsCExternalHandlerService.h>
+#include <nsComponentManagerUtils.h>
+#include <nsIDOMWindow.h>
+#include <nsIInterfaceRequestorUtils.h>
+#include <nsILocalFile.h>
+#include <nsIMIMEInfo.h>
+#include <nsIURL.h>
+#include <nsMemory.h>
+#include <nsNetError.h>
+#include <nsServiceManagerUtils.h>
+
+#include "eel-gconf-extensions.h"
+#include "ephy-debug.h"
+#include "ephy-embed-shell.h"
+#include "ephy-embed-single.h"
+#include "ephy-file-chooser.h"
+#include "ephy-file-helpers.h"
+#include "ephy-gui.h"
+#include "ephy-prefs.h"
+#include "ephy-stock-icons.h"
+
+#include "AutoJSContextStack.h"
+#include "AutoWindowModalState.h"
+#include "EphyUtils.h"
+#include "MozDownload.h"
+
+#include "ContentHandler.h"
+
+/* FIXME: we don't generally have a timestamp for the user action which initiated this
+ * content handler.
+ */
+GContentHandler::GContentHandler()
+: mUserTime(0)
+{
+ LOG ("GContentHandler ctor (%p)", this);
+}
+
+GContentHandler::~GContentHandler()
+{
+ LOG ("GContentHandler dtor (%p)", this);
+}
+
+NS_IMPL_ISUPPORTS1(GContentHandler, nsIHelperAppLauncherDialog)
+
+/* void show (in nsIHelperAppLauncher aLauncher, in nsISupports aContext, in unsigned long aReason); */
+NS_IMETHODIMP
+GContentHandler::Show (nsIHelperAppLauncher *aLauncher,
+ nsISupports *aContext,
+ PRUint32 aReason)
+{
+ nsresult rv;
+ EphyEmbedSingle *single;
+ gboolean handled = FALSE;
+
+ /* FIXME: handle aForced / aReason argument in some way? */
+
+ mContext = aContext;
+
+ /* Check for a potential veto */
+ nsCOMPtr<nsIDOMWindow> window (do_GetInterface (aContext));
+ GtkWidget *embed = EphyUtils::FindEmbed (window);
+ if (EPHY_IS_EMBED (embed))
+ {
+ if (g_object_get_data (G_OBJECT (embed), "content-handler-deny"))
+ {
+ return NS_OK;
+ }
+ }
+
+ mLauncher = aLauncher;
+ rv = Init ();
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ single = EPHY_EMBED_SINGLE (ephy_embed_shell_get_embed_single (embed_shell));
+ g_signal_emit_by_name (single, "handle_content", mMimeType.get(),
+ mUrl.get(), &handled);
+
+ if (!handled)
+ {
+ MIMEInitiateAction ();
+ }
+ else
+ {
+ mLauncher->Cancel (NS_BINDING_ABORTED);
+ }
+
+ return NS_OK;
+}
+
+/* nsILocalFile promptForSaveToFile (in nsISupports aWindowContext, in wstring aDefaultFile, in wstring aSuggestedFileExtension); */
+NS_IMETHODIMP GContentHandler::PromptForSaveToFile(
+ nsIHelperAppLauncher *aLauncher,
+ nsISupports *aWindowContext,
+ const PRUnichar *aDefaultFile,
+ const PRUnichar *aSuggestedFileExtension,
+ nsILocalFile **_retval)
+{
+ EphyFileChooser *dialog;
+ int response;
+ char *filename = NULL;
+ nsCString defaultFile;
+
+ NS_UTF16ToCString (nsString (aDefaultFile),
+ NS_CSTRING_ENCODING_UTF8, defaultFile);
+
+ if (mAction != CONTENT_ACTION_SAVEAS)
+ {
+ return BuildDownloadPath (defaultFile.get(), _retval);
+ }
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ nsCOMPtr<nsIDOMWindow> parentDOMWindow (do_GetInterface (aWindowContext));
+ GtkWidget *parentWindow = GTK_WIDGET (EphyUtils::FindGtkParent (parentDOMWindow));
+
+ AutoWindowModalState modalState (parentDOMWindow);
+
+ dialog = ephy_file_chooser_new (_("Save"), parentWindow,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ CONF_STATE_SAVE_DIR,
+ EPHY_FILE_FILTER_ALL);
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), defaultFile.get());
+
+ if (parentWindow)
+ {
+ gtk_window_group_add_window (ephy_gui_ensure_window_group (GTK_WINDOW (parentWindow)),
+ GTK_WINDOW (dialog));
+ }
+
+ /* FIXME: this will only be the real user time if we came from ::Show */
+ ephy_gui_window_update_user_time (GTK_WIDGET (dialog), (guint32) mUserTime);
+
+ /* FIXME: modal -- mozilla sucks! */
+ do
+ {
+ g_free (filename);
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ } while (response == GTK_RESPONSE_ACCEPT
+ && !ephy_gui_check_location_writable (GTK_WIDGET (dialog), filename));
+
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ nsCOMPtr <nsILocalFile> destFile (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+ NS_ENSURE_TRUE (destFile, NS_ERROR_FAILURE);
+
+ destFile->InitWithNativePath (nsCString (filename));
+ g_free (filename);
+
+ NS_IF_ADDREF (*_retval = destFile);
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ return NS_OK;
+ }
+ else
+ {
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ g_free (filename);
+
+ return NS_ERROR_FAILURE;
+ }
+}
+
+NS_METHOD GContentHandler::Init ()
+{
+ nsresult rv;
+
+ NS_ENSURE_TRUE (mLauncher, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIMIMEInfo> MIMEInfo;
+ mLauncher->GetMIMEInfo (getter_AddRefs(MIMEInfo));
+ NS_ENSURE_TRUE (MIMEInfo, NS_ERROR_FAILURE);
+
+ rv = MIMEInfo->GetMIMEType (mMimeType);
+
+ nsCOMPtr<nsIURI> uri;
+ mLauncher->GetSource (getter_AddRefs(uri));
+ NS_ENSURE_TRUE (uri, NS_ERROR_FAILURE);
+
+ uri->GetSpec (mUrl);
+
+ return NS_OK;
+}
+
+static void
+response_cb (GtkWidget *dialog,
+ int response,
+ GContentHandler *self)
+{
+ gtk_widget_destroy (dialog);
+
+ if (response > 0)
+ {
+ self->mAction = (ContentAction) response;
+ }
+ else
+ {
+ self->mAction = CONTENT_ACTION_NONE;
+ }
+
+ self->MIMEDoAction ();
+}
+
+static void
+release_cb (GContentHandler *data)
+{
+ NS_RELEASE (data);
+}
+
+NS_METHOD GContentHandler::MIMEConfirmAction ()
+{
+ GtkWidget *dialog, *button, *image;
+ const char *action_label;
+ const char *mime_description;
+ nsCString file_name;
+
+ nsCOMPtr<nsIDOMWindow> parentDOMWindow = do_GetInterface (mContext);
+ GtkWindow *parentWindow = GTK_WINDOW (EphyUtils::FindGtkParent(parentDOMWindow));
+
+ action_label = (mAction == CONTENT_ACTION_OPEN) ||
+ (mAction == CONTENT_ACTION_OPEN_TMP) ?
+ GTK_STOCK_OPEN : STOCK_DOWNLOAD;
+
+ mime_description = gnome_vfs_mime_get_description (mMimeType.get());
+ if (mime_description == NULL)
+ {
+ /* Translators: The text before the "|" is context to help you decide on
+ * the correct translation. You MUST OMIT it in the translated string. */
+ mime_description = Q_("File Type:|Unknown");
+ }
+
+ /* We have one tiny, minor issue, the filename can be empty (""),
+ is that severe enough to be completely fixed ? */
+ nsString suggested;
+
+ mLauncher->GetSuggestedFileName (suggested);
+ NS_UTF16ToCString (suggested,
+ NS_CSTRING_ENCODING_UTF8, file_name);
+
+ if (mPermission != EPHY_MIME_PERMISSION_SAFE && mHelperApp)
+ {
+ dialog = gtk_message_dialog_new
+ (parentWindow, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE,
+ _("Download this potentially unsafe file?"));
+
+ gtk_message_dialog_format_secondary_text
+ (GTK_MESSAGE_DIALOG (dialog),
+ /* translators: First %s is the file type description,
+ Second %s is the file name */
+ _("File Type: “%s”.\n\nIt is unsafe to open “%s” as "
+ "it could potentially damage your documents or "
+ "invade your privacy. You can download it instead."),
+ mime_description, file_name.get());
+ }
+ else if (mAction == CONTENT_ACTION_OPEN_TMP && mHelperApp)
+ {
+ dialog = gtk_message_dialog_new
+ (parentWindow, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
+ _("Open this file?"));
+
+ gtk_message_dialog_format_secondary_text
+ (GTK_MESSAGE_DIALOG (dialog),
+ /* translators: First %s is the file type description,
+ Second %s is the file name,
+ Third %s is the application used to open the file */
+ _("File Type: “%s”.\n\nYou can open “%s” using “%s” or save it."),
+ mime_description, file_name.get(), mHelperApp->name);
+ }
+ else
+ {
+ dialog = gtk_message_dialog_new
+ (parentWindow, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
+ _("Download this file?"));
+
+ gtk_message_dialog_format_secondary_text
+ (GTK_MESSAGE_DIALOG (dialog),
+ /* translators: First %s is the file type description,
+ Second %s is the file name */
+ _("File Type: “%s”.\n\nYou have no application able to open “%s”. "
+ "You can download it instead."),
+ mime_description, file_name.get());
+ }
+
+ button = gtk_button_new_with_label (_("_Save As..."));
+ image = gtk_image_new_from_stock (GTK_STOCK_SAVE_AS, GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ /* don't show the image! see bug #307818 */
+ gtk_widget_show (button);
+ gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, CONTENT_ACTION_SAVEAS);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (dialog),
+ action_label, mAction);
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ int defaultResponse = mAction == CONTENT_ACTION_NONE
+ ? (int) GTK_RESPONSE_CANCEL
+ : (int) mAction;
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), defaultResponse);
+
+ NS_ADDREF_THIS();
+ g_signal_connect_data (dialog, "response",
+ G_CALLBACK (response_cb), this,
+ (GClosureNotify) release_cb, (GConnectFlags) 0);
+
+ /* FIXME: should find a way to get the user time of the user action which
+ * initiated this content handler
+ */
+ gtk_window_present (GTK_WINDOW (dialog));
+
+ return NS_OK;
+}
+
+NS_METHOD GContentHandler::MIMEInitiateAction (void)
+{
+ gboolean auto_downloads;
+
+ if (eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_SAVE_TO_DISK)) return NS_OK;
+
+ auto_downloads = eel_gconf_get_boolean (CONF_AUTO_DOWNLOADS);
+
+ mHelperApp = gnome_vfs_mime_get_default_application (mMimeType.get());
+ mPermission = ephy_file_check_mime (mMimeType.get());
+
+ /* HACK! Check that this 'helper application' isn't Epiphany itself,
+ * see bug #310023.
+ */
+ if (mHelperApp)
+ {
+ const char *id = gnome_vfs_mime_application_get_desktop_id (mHelperApp);
+
+ /* FIXME! menu editing can make this check fail!!!! */
+ if (id && strcmp (id, "epiphany.desktop") == 0)
+ {
+ mHelperApp = nsnull;
+ }
+ }
+
+ if (auto_downloads)
+ {
+ mAction = CONTENT_ACTION_OPEN;
+ }
+ else
+ {
+ mAction = CONTENT_ACTION_OPEN_TMP;
+ }
+
+ if (!mHelperApp || mPermission != EPHY_MIME_PERMISSION_SAFE)
+ {
+ mAction = CONTENT_ACTION_DOWNLOAD;
+ }
+
+ if (!auto_downloads || mAction == CONTENT_ACTION_DOWNLOAD)
+ {
+ MIMEConfirmAction ();
+ }
+ else
+ {
+ MIMEDoAction ();
+ }
+
+ return NS_OK;
+}
+
+NS_METHOD GContentHandler::MIMEDoAction (void)
+{
+ /* This is okay, since we either clicked on a button, or we get 0 */
+ mUserTime = gtk_get_current_event_time ();
+
+ nsCOMPtr<nsIMIMEInfo> mimeInfo;
+ mLauncher->GetMIMEInfo(getter_AddRefs(mimeInfo));
+ NS_ENSURE_TRUE (mimeInfo, NS_ERROR_FAILURE);
+
+ char *info = NULL;
+
+ if (mAction == CONTENT_ACTION_OPEN)
+ {
+ g_return_val_if_fail (mHelperApp, NS_ERROR_FAILURE);
+
+ const char *id;
+ id = gnome_vfs_mime_application_get_desktop_id (mHelperApp);
+
+ /* The current time is fine here as the user has just clicked
+ * a button (it is used as the time for the application opening)
+ */
+ info = g_strdup_printf ("gnome-default:%d:%s", gtk_get_current_event_time(), id);
+ }
+ else if (mAction == CONTENT_ACTION_DOWNLOAD)
+ {
+ info = g_strdup_printf ("gnome-browse-to-file:%d", gtk_get_current_event_time());
+ }
+
+ /* See http://bugzilla.gnome.org/show_bug.cgi?id=456945 */
+#ifndef HAVE_GECKO_1_9
+ if (info != NULL)
+ {
+ nsString desc;
+ NS_CStringToUTF16 (nsCString (info),
+ NS_CSTRING_ENCODING_UTF8, desc);
+ g_free (info);
+
+ /* HACK we use the application description to ask
+ MozDownload to open the file when download
+ is finished */
+ mimeInfo->SetApplicationDescription (desc);
+ }
+ else
+ {
+ mimeInfo->SetApplicationDescription (nsString ());
+ }
+#endif /* HAVE_GECKO_1_9 */
+
+ if (mAction == CONTENT_ACTION_OPEN)
+ {
+ mLauncher->SaveToDisk (nsnull, PR_FALSE);
+ }
+ else if (mAction == CONTENT_ACTION_OPEN_TMP)
+ {
+ mLauncher->LaunchWithApplication (nsnull, PR_FALSE);
+ }
+ else if (mAction == CONTENT_ACTION_NONE)
+ {
+ mLauncher->Cancel (NS_BINDING_ABORTED);
+ }
+ else
+ {
+ mLauncher->SaveToDisk (nsnull, PR_FALSE);
+ }
+
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/ContentHandler.h b/embed/xulrunner/embed/ContentHandler.h
new file mode 100644
index 000000000..113e29070
--- /dev/null
+++ b/embed/xulrunner/embed/ContentHandler.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright © 2000-2003 Marco Pesenti Gritti,
+ * Copyright © 2003 Xan Lopez
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef CONTENT_HANDLER_H
+#define CONTENT_HANDLER_H
+
+#include <libgnomevfs/gnome-vfs-mime-handlers.h>
+
+#include <nsCOMPtr.h>
+#include <nsIFile.h>
+#include <nsIHelperAppLauncherDialog.h>
+#include <nsIURI.h>
+
+#include "ephy-file-helpers.h"
+
+
+typedef enum
+{
+ CONTENT_ACTION_OPEN = 1,
+ CONTENT_ACTION_OPEN_TMP,
+ CONTENT_ACTION_DOWNLOAD,
+ CONTENT_ACTION_SAVEAS,
+ CONTENT_ACTION_NONE
+} ContentAction;
+
+#define G_CONTENTHANDLER_CID \
+{ /* 16072c4a-23a6-4996-9beb-9335c06bbeae */ \
+ 0x16072c4a, \
+ 0x23a6, \
+ 0x4996, \
+ {0x9b, 0xeb, 0x93, 0x35, 0xc0, 0x6b, 0xbe, 0xae} \
+}
+
+class GContentHandler : public nsIHelperAppLauncherDialog
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIHELPERAPPLAUNCHERDIALOG
+
+ GContentHandler();
+ virtual ~GContentHandler();
+
+ NS_METHOD MIMEDoAction ();
+ ContentAction mAction;
+ private:
+
+ NS_METHOD Init ();
+
+ NS_METHOD MIMEInitiateAction ();
+ NS_METHOD MIMEConfirmAction ();
+
+ nsCOMPtr<nsIHelperAppLauncher> mLauncher;
+ nsCOMPtr<nsISupports> mContext;
+
+ GnomeVFSMimeApplication *mHelperApp;
+ EphyMimePermission mPermission;
+
+ nsCString mUrl;
+ nsCString mMimeType;
+ PRUint32 mUserTime;
+};
+
+#endif /* CONTENT_HANDLER_H */
diff --git a/embed/xulrunner/embed/EphyAboutModule.cpp b/embed/xulrunner/embed/EphyAboutModule.cpp
new file mode 100644
index 000000000..6fb6a5849
--- /dev/null
+++ b/embed/xulrunner/embed/EphyAboutModule.cpp
@@ -0,0 +1,725 @@
+/*
+ * Copyright © 2001 Matt Aubury, Philip Langdale
+ * Copyright © 2004 Crispin Flowerday
+ * Copyright © 2005 Christian Persch
+ * Copyright © 2005 Adam Hooper
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+// we need nsEscape which depends on internal strings :(((
+#define MOZILLA_INTERNAL_API 1
+#include <nsString.h>
+
+#include <nsAutoPtr.h>
+#include <nsCOMPtr.h>
+#include <nsEscape.h>
+#include <nsIChannel.h>
+#include <nsIInputStreamChannel.h>
+#include <nsIInputStream.h>
+#include <nsIIOService.h>
+#include <nsIOutputStream.h>
+#include <nsIScriptSecurityManager.h>
+#include <nsIStorageStream.h>
+#include <nsIURI.h>
+#include <nsNetCID.h>
+#include <nsNetUtil.h>
+#include <nsServiceManagerUtils.h>
+
+#include "ephy-debug.h"
+
+#include "EphyRedirectChannel.h"
+
+#include "EphyAboutModule.h"
+
+EphyAboutModule::EphyAboutModule()
+{
+ LOG ("EphyAboutModule ctor [%p]\n", this);
+}
+
+EphyAboutModule::~EphyAboutModule()
+{
+ LOG ("EphyAboutModule dtor [%p]\n", this);
+}
+
+NS_IMPL_ISUPPORTS1 (EphyAboutModule, nsIAboutModule)
+
+/* nsIChannel newChannel (in nsIURI aURI); */
+NS_IMETHODIMP
+EphyAboutModule::NewChannel(nsIURI *aURI,
+ nsIChannel **_retval)
+{
+ NS_ENSURE_ARG(aURI);
+
+ nsCAutoString path;
+ aURI->GetPath (path);
+
+ if (strncmp (path.get(), "neterror?", strlen ("neterror?")) == 0)
+ {
+ return CreateErrorPage (aURI, _retval);
+ }
+
+ if (strncmp (path.get (), "recover?", strlen ("recover?")) == 0)
+ {
+ return CreateRecoverPage (aURI, _retval);
+ }
+
+ if (strcmp (path.get (), "epiphany") == 0)
+ {
+ return Redirect (nsDependentCString ("file://" SHARE_DIR "/epiphany.xhtml"), _retval);
+ }
+
+ return NS_ERROR_ILLEGAL_VALUE;
+}
+
+#ifdef HAVE_GECKO_1_9
+/* unsigned long getURIFlags(in nsIURI aURI); */
+NS_IMETHODIMP
+EphyAboutModule::GetURIFlags (nsIURI *aURI,
+ PRUint32 *_result)
+{
+ *_result = 0;
+ return NS_OK;
+}
+#endif
+
+/* private functions */
+
+nsresult
+EphyAboutModule::Redirect(const nsACString &aURL,
+ nsIChannel **_retval)
+{
+ *_retval = nsnull;
+
+ nsresult rv;
+ nsCOMPtr<nsIURI> uri;
+ rv = NS_NewURI (getter_AddRefs (uri), aURL);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIChannel> tempChannel;
+ rv = NS_NewChannel (getter_AddRefs (tempChannel), uri);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ tempChannel->SetOriginalURI (uri);
+
+ nsCOMPtr<nsIScriptSecurityManager> securityManager =
+ do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIPrincipal> principal;
+ rv = securityManager->GetCodebasePrincipal(uri, getter_AddRefs(principal));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = tempChannel->SetOwner(principal);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ tempChannel.swap (*_retval);
+
+ return NS_OK;
+}
+
+nsresult
+EphyAboutModule::ParseURL(const char *aURL,
+ nsACString &aCode,
+ nsACString &aRawOriginURL,
+ nsACString &aOriginURL,
+ nsACString &aOriginCharset,
+ nsACString &aTitle)
+{
+ /* The page URL is of the form "about:neterror?e=<errorcode>&u=<URL>&c=<charset>&d=<description>" */
+ const char *query = strstr (aURL, "?");
+ if (!query) return NS_ERROR_FAILURE;
+
+ /* skip the '?' */
+ ++query;
+
+ char **params = g_strsplit (query, "&", -1);
+ if (!params) return NS_ERROR_FAILURE;
+
+ for (PRUint32 i = 0; params[i] != NULL; ++i)
+ {
+ char *param = params[i];
+
+ if (strlen (param) <= 2) continue;
+
+ switch (param[0])
+ {
+ case 'e':
+ aCode.Assign (nsUnescape (param + 2));
+ break;
+ case 'u':
+ aRawOriginURL.Assign (param + 2);
+ aOriginURL.Assign (nsUnescape (param + 2));
+ break;
+ case 'c':
+ aOriginCharset.Assign (nsUnescape (param + 2));
+ break;
+ /* The next one is not used in neterror but recover: */
+ case 't':
+ aTitle.Assign (nsUnescape (param + 2));
+ break;
+ case 'd':
+ /* we don't need mozilla's description parameter */
+ default:
+ break;
+ }
+ }
+
+ g_strfreev (params);
+
+ return NS_OK;
+}
+
+nsresult
+EphyAboutModule::GetErrorMessage(nsIURI *aURI,
+ const char *aError,
+ char **aStockIcon,
+ char **aTitle,
+ char **aPrimary,
+ char **aSecondary,
+ char **aTertiary,
+ char **aLinkIntro)
+{
+ *aStockIcon = GTK_STOCK_DIALOG_ERROR;
+
+ if (strcmp (aError, "protocolNotFound") == 0)
+ {
+ nsCAutoString scheme;
+ aURI->GetScheme (scheme);
+
+ /* Translators: %s is the name of a protocol, like "http" etc. */
+ *aTitle = g_strdup_printf (_("“%s” Protocol is not Supported"), scheme.get());
+ /* Translators: %s is the name of a protocol, like "http" etc. */
+ *aPrimary = g_strdup_printf (_("“%s” protocol is not supported."), scheme.get());
+ /* FIXME: get the list of supported protocols from necko */
+ *aSecondary = g_strdup (_("Supported protocols are “http”, “https”, “ftp”, “file”, “smb” "
+ "and “sftp”."));
+ }
+ else if (strcmp (aError, "fileNotFound") == 0)
+ {
+ nsCAutoString path;
+ aURI->GetPath (path);
+
+ /* Translators: %s is the path and filename, for example "/home/user/test.html" */
+ *aTitle = g_markup_printf_escaped (_("File “%s” not Found"), path.get());
+ /* Translators: %s is the path and filename, for example "/home/user/test.html" */
+ *aPrimary = g_markup_printf_escaped (_("File “%s” not found."), path.get());
+ *aSecondary = g_strdup (_("Check the location of the file and try again."));
+ }
+ else if (strcmp (aError, "dnsNotFound") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aTitle = g_markup_printf_escaped (_("“%s” Could not be Found"),
+ host.get());
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped (_("“%s” could not be found."),
+ host.get());
+ *aSecondary = g_strdup (_("Check that you are connected to the internet, and "
+ "that the address is correct."));
+ *aLinkIntro = _("If this page used to exist, you may find an archived version:");
+ }
+ else if (strcmp (aError, "connectionFailure") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aTitle = g_markup_printf_escaped
+ (_("“%s” Refused the Connection"),
+ host.get());
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” refused the connection."),
+ host.get());
+
+ /* FIXME what about 127.0.0.* ? */
+ if (strcmp (host.get(), "localhost") == 0)
+ {
+ PRInt32 port;
+ aURI->GetPort (&port);
+
+ *aSecondary = g_strdup (_("Likely causes of the problem are"));
+
+ /* Try to get the service name attached to that port */
+ if (port != -1)
+ {
+ struct servent *serv;
+
+ if ((serv = getservbyport (htons (port), NULL)) != NULL)
+ {
+ *aTertiary = g_markup_printf_escaped (
+ _("<ul>"
+ "<li>the service ""%s"" isn't started.</li>"
+ "Try to start it using the Services Configuration Tool in "
+ "System > Control Center, or</ul>"
+ "<ul><li>the port number %d is wrong.</li>"
+ "</ul>"),
+ serv->s_name, port);
+ }
+ else
+ {
+ *aTertiary = g_markup_printf_escaped (
+ _("<ul>"
+ "<li>some service isn't started, or</li>"
+ "<li>the port number %d is wrong.</li>"
+ "</ul>"),
+ port);
+ }
+ }
+ else
+ {
+ *aTertiary = _("<ul>"
+ "<li>some service isn't started, or</li>"
+ "<li>you got the port number wrong.</li>"
+ "</ul>");
+ }
+ }
+ else
+ {
+ *aSecondary = g_strdup (_("The server may be busy or you may have a "
+ "network connection problem. Try again later."));
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ }
+ else if (strcmp (aError, "netInterrupt") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aTitle = g_markup_printf_escaped
+ (_("“%s” Interrupted the Connection"),
+ host.get());
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” interrupted the connection."),
+ host.get());
+ *aSecondary = g_strdup (_("The server may be busy or you may have a "
+ "network connection problem. Try again later."));
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "netTimeout") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aTitle = g_markup_printf_escaped
+ (_("“%s” is not Responding"),
+ host.get());
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” is not responding."),
+ host.get());
+ *aSecondary = g_strdup (_("The connection was lost because the "
+ "server took too long to respond."));
+ *aTertiary = _("The server may be busy or you may have a network "
+ "connection problem. Try again later.");
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "malformedURI") == 0)
+ {
+ *aTitle = g_strdup (_("Invalid Address"));
+ *aPrimary = g_strdup (_("Invalid address."));
+ *aSecondary = g_strdup (_("The address you entered is not valid."));
+ }
+ else if (strcmp (aError, "redirectLoop") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aTitle = g_markup_printf_escaped
+ (_("“%s” Redirected Too Many Times"),
+ host.get());
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_strdup (_("This page cannot load because of a problem with the Web site."));
+
+ *aSecondary = g_markup_printf_escaped
+ (_("The server “%s” is redirecting in a way that will never complete."),
+ host.get());
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "unknownSocketType") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aTitle = g_markup_printf_escaped
+ (_("“%s” Requires an Encrypted Connection"),
+ host.get());
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” requires an encrypted connection."),
+ host.get());
+ *aSecondary = g_strdup (_("The document could not be loaded because "
+ "encryption support is not installed."));
+ }
+ else if (strcmp (aError, "netReset") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aTitle = g_markup_printf_escaped
+ (_("“%s” Dropped the Connection"),
+ host.get());
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” dropped the connection."),
+ host.get());
+ *aSecondary = g_strdup (_("The server dropped the connection "
+ "before any data could be read."));
+ *aTertiary = _("The server may be busy or you may have a "
+ "network connection problem. Try again later.");
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "netOffline") == 0)
+ {
+ /* Error is a bit too strong here */
+ *aStockIcon = GTK_STOCK_DIALOG_INFO;
+
+ *aTitle = g_strdup (_("Cannot Load Document Whilst Working Offline"));
+ *aPrimary = g_strdup (_("Cannot load document whilst working offline."));
+ *aSecondary = g_strdup (_("To view this document, disable “Work Offline” and try again."));
+ }
+ else if (strcmp (aError, "deniedPortAccess") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ PRInt32 port = -1;
+ aURI->GetPort (&port);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aTitle = g_markup_printf_escaped
+ (_("“%s” Denied Access to Port “%d”"),
+ host.get(), port > 0 ? port : 80);
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” denied access to port “%d”."),
+ host.get(), port > 0 ? port : 80);
+ *aSecondary = g_strdup (_("The server dropped the connection "
+ "before any data could be read."));
+ *aTertiary = _("The server may be busy or you may have a "
+ "network connection problem. Try again later.");
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "proxyResolveFailure") == 0 ||
+ strcmp (aError, "proxyConnectFailure") == 0)
+ {
+ *aTitle = g_strdup (_("Could not Connect to Proxy Server"));
+ *aPrimary = g_strdup (_("Could not connect to proxy server."));
+ *aSecondary = g_strdup (_("Check your proxy server settings. "
+ "If the connection still fails, there may be "
+ "a problem with your proxy server or your "
+ "network connection."));
+ }
+ /* This was introduced in gecko 1.9 */
+ else if (strcmp (aError, "contentEncodingError") == 0)
+ {
+ *aTitle = g_strdup (_("Could not Display Content"));
+ *aPrimary = g_strdup (_("Could not display content."));
+ *aSecondary = g_strdup (_("The page uses an unsupported or invalid form of compression."));
+ }
+ else
+ {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+EphyAboutModule::CreateErrorPage(nsIURI *aErrorURI,
+ nsIChannel **_retval)
+{
+ *_retval = nsnull;
+
+ /* First parse the arguments */
+ nsresult rv;
+ nsCAutoString spec;
+ rv = aErrorURI->GetSpec (spec);
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv), rv);
+
+ nsCAutoString error, rawurl, url, charset, dummy;
+ rv = ParseURL (spec.get (), error, rawurl, url, charset, dummy);
+ if (NS_FAILED (rv)) return rv;
+ if (error.IsEmpty () || rawurl.IsEmpty () || url.IsEmpty()) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIURI> uri;
+ rv = NS_NewURI (getter_AddRefs (uri), url, charset.get());
+ /* FIXME can uri be NULL if the original url was invalid? */
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ char *stock_id = nsnull, *title = nsnull, *primary = nsnull,
+ *secondary = nsnull, *tertiary = nsnull, *linkintro = nsnull;
+ rv = GetErrorMessage (uri, error.get(), &stock_id, &title, &primary,
+ &secondary, &tertiary, &linkintro);
+
+ /* we don't know about this error code.
+ * FIXME: We'd like to forward to mozilla's about:neterror handler,
+ * but I don't know how to. So just redirect to the same page that
+ * mozilla's handler redirects to.
+ */
+ if (rv == NS_ERROR_ILLEGAL_VALUE)
+ {
+ nsCAutoString newurl(spec);
+
+ /* remove "about:neterror" part and insert mozilla's error page url */
+ newurl.Cut(0, strlen ("about:neterror"));
+ newurl.Insert("chrome://global/content/netError.xhtml", 0);
+
+ return Redirect (newurl, _retval);
+ }
+ NS_ENSURE_SUCCESS (rv, rv);
+ NS_ENSURE_TRUE (primary && secondary, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIChannel> channel;
+ rv = WritePage (aErrorURI, uri, aErrorURI, rawurl, title, stock_id, primary, secondary, tertiary, linkintro, getter_AddRefs (channel));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ g_free (title);
+ g_free (primary);
+ g_free (secondary);
+
+ channel.swap (*_retval);
+
+ return NS_OK;
+}
+
+nsresult
+EphyAboutModule::CreateRecoverPage(nsIURI *aRecoverURI,
+ nsIChannel **_retval)
+{
+ *_retval = nsnull;
+
+ /* First parse the arguments */
+ nsresult rv;
+ nsCAutoString spec;
+ rv = aRecoverURI->GetSpec (spec);
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv), rv);
+
+ nsCAutoString error, rawurl, url, charset, title;
+ rv = ParseURL (spec.get (), error, rawurl, url, charset, title);
+ if (NS_FAILED (rv)) return rv;
+ if (rawurl.IsEmpty () || url.IsEmpty()) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIURI> uri;
+ rv = NS_NewURI(getter_AddRefs (uri), url, charset.get());
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ char *secondary = g_markup_printf_escaped
+ (_("The page “%s” in this tab was not fully loaded yet when "
+ "the web browser crashed; it could have caused the crash."),
+ url.get());
+
+ nsCOMPtr<nsIChannel> channel;
+ rv = WritePage (aRecoverURI, uri, uri, rawurl, title.get(),
+ GTK_STOCK_DIALOG_INFO, title.get() /* as primary */,
+ secondary, nsnull, nsnull, getter_AddRefs (channel));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsRefPtr<EphyRedirectChannel> redirectChannel (new EphyRedirectChannel (channel));
+ if (!redirectChannel) return NS_ERROR_OUT_OF_MEMORY;
+
+ g_free (secondary);
+
+ NS_ADDREF(*_retval = redirectChannel);
+
+ return NS_OK;
+}
+
+nsresult
+EphyAboutModule::WritePage(nsIURI *aOriginalURI,
+ nsIURI *aURI,
+ nsIURI *aChannelURI,
+ const nsACString &aRawURL,
+ const char *aTitle,
+ const char *aStockIcon,
+ const char *aPrimary,
+ const char *aSecondary,
+ const char *aTertiary,
+ const char *aLinkIntro,
+ nsIChannel **_retval)
+{
+ *_retval = nsnull;
+
+ nsresult rv;
+ nsCOMPtr<nsIStorageStream> storageStream;
+ rv = NS_NewStorageStream (16384, (PRUint32) -1, getter_AddRefs (storageStream));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIOutputStream> stream;
+ rv = storageStream->GetOutputStream (0, getter_AddRefs (stream));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ char *language = g_strdup (pango_language_to_string (gtk_get_default_language ()));
+ g_strdelimit (language, "_-@", '\0');
+
+ Write (stream,
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
+ "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"");
+ Write (stream, language);
+ Write (stream,
+ "\" xml:lang=\"");
+ Write (stream, language);
+ Write (stream,
+ "\">\n"
+ "<head>\n"
+ "<title>");
+ Write (stream, aTitle);
+ /* no favicon for now, it would pollute the favicon cache */
+ /* "<link rel=\"icon\" type=\"image/png\" href=\"moz-icon://stock/gtk-dialog-error?size=16\" />\n" */
+ Write (stream,
+ "</title>\n"
+ "<style type=\"text/css\">\n"
+ "div#body {\n"
+ "top: 12px;\n"
+ "right: 12px;\n"
+ "bottom: 12px;\n"
+ "left: 12px;\n"
+ "overflow: auto;\n"
+
+ "background: -moz-dialog url('moz-icon://stock/");
+ Write (stream, aStockIcon);
+ Write (stream,
+ "?size=dialog') no-repeat 12px 12px;\n"
+ "color: -moz-dialogtext;\n"
+ "font: message-box;\n"
+ "border: 1px solid -moz-dialogtext;\n"
+
+ "padding: 12px 12px 12px 72px;\n"
+ "}\n"
+
+ "h1 {\n"
+ "margin: 0;\n"
+ "font-size: 1.2em;\n"
+ "}\n"
+ "</style>\n"
+ "</head>\n"
+ "<body dir=\"");
+ Write (stream,
+ gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL ? "rtl" : "ltr");
+ Write (stream,
+ "\">\n"
+ "<div id=\"body\">"
+ "<h1>");
+ Write (stream, aPrimary);
+ Write (stream,
+ "</h1>\n");
+ if (aSecondary)
+ {
+ Write (stream, "<p>");
+ Write (stream, aSecondary);
+ if (aTertiary)
+ {
+ Write (stream, " ");
+ Write (stream, aTertiary);
+ }
+ Write (stream, "</p>\n");
+ }
+
+ PRBool isHttp = PR_FALSE, isHttps = PR_FALSE;
+ aURI->SchemeIs ("http", &isHttp);
+ aURI->SchemeIs ("https", &isHttps);
+ if (aLinkIntro && (isHttp || isHttps))
+ {
+ nsCString raw(aRawURL);
+
+ Write (stream, "<p>");
+ Write (stream, aLinkIntro);
+ Write (stream, "<ul>\n");
+ Write (stream, "<li><a href=\"http://www.google.com/search?q=cache:");
+ Write (stream, raw.get());
+ Write (stream, "\">");
+ /* Translators: The text before the "|" is context to help you decide on
+ * the correct translation. You MUST OMIT it in the translated string. */
+ Write (stream, Q_("You may find an old version:|in the Google Cache"));
+ Write (stream, "</a></li>\n");
+
+ Write (stream, "<li><a href=\"http://web.archive.org/web/*/");
+ Write (stream, raw.get());
+ Write (stream, "\">");
+ /* Translators: The text before the "|" is context to help you decide on
+ * the correct translation. You MUST OMIT it in the translated string. */
+ Write (stream, Q_("You may find an old version:|in the Internet Archive"));
+ Write (stream, "</a></li>\n"
+ "</ul>\n"
+ "</p>");
+ }
+
+ Write (stream,
+ "</div>\n"
+ "</body>\n"
+ "</html>\n");
+
+ g_free (language);
+
+ /* finish the rendering */
+ nsCOMPtr<nsIInputStream> inputStream;
+ rv = storageStream->NewInputStream (0, getter_AddRefs (inputStream));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIChannel> channel;
+ rv = NS_NewInputStreamChannel (getter_AddRefs (channel),
+ aChannelURI,
+ inputStream,
+ NS_LITERAL_CSTRING ("application/xhtml+xml"),
+ NS_LITERAL_CSTRING ("utf-8"));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = channel->SetOriginalURI (aOriginalURI);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIScriptSecurityManager> securityManager
+ (do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIPrincipal> principal;
+ rv = securityManager->GetCodebasePrincipal (aOriginalURI, getter_AddRefs (principal));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = channel->SetOwner(principal);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ channel.swap (*_retval);
+
+ return NS_OK;
+}
+
+nsresult
+EphyAboutModule::Write(nsIOutputStream *aStream,
+ const char *aText)
+{
+ PRUint32 bytesWritten;
+ return aStream->Write (aText, strlen (aText), &bytesWritten);
+}
diff --git a/embed/xulrunner/embed/EphyAboutModule.h b/embed/xulrunner/embed/EphyAboutModule.h
new file mode 100644
index 000000000..21a269c49
--- /dev/null
+++ b/embed/xulrunner/embed/EphyAboutModule.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright © 2001 Matt Aubury, Philip Langdale
+ * Copyright © 2004 Crispin Flowerday
+ * Copyright © 2005 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_ABOUT_MODULE_H
+#define EPHY_ABOUT_MODULE_H
+
+#include <nsIAboutModule.h>
+
+/* a9aea13e-21de-4be8-a07e-a05f11658c55 */
+#define EPHY_ABOUT_MODULE_CID \
+{ 0xa9aea13e, 0x21de, 0x4be8, \
+ { 0xa0, 0x7e, 0xa0, 0x5f, 0x11, 0x65, 0x8c, 0x55 } }
+
+#define EPHY_ABOUT_NETERROR_CONTRACTID NS_ABOUT_MODULE_CONTRACTID_PREFIX "neterror"
+#define EPHY_ABOUT_NETERROR_CLASSNAME "Epiphany about:neterror module"
+
+#define EPHY_ABOUT_EPIPHANY_CONTRACTID NS_ABOUT_MODULE_CONTRACTID_PREFIX "epiphany"
+#define EPHY_ABOUT_EPIPHANY_CLASSNAME "Epiphany about:epiphany module"
+#define EPHY_ABOUT_RECOVER_CONTRACTID NS_ABOUT_MODULE_CONTRACTID_PREFIX "recover"
+#define EPHY_ABOUT_RECOVER_CLASSNAME "Epiphany about:recover module"
+
+class nsIChannel;
+class nsIOutputStream;
+class nsIInputStreamChannel;
+class nsIURI;
+
+class EphyAboutModule : public nsIAboutModule
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIABOUTMODULE
+
+ EphyAboutModule();
+ virtual ~EphyAboutModule();
+
+ private:
+ nsresult Redirect(const nsACString&, nsIChannel**);
+ nsresult ParseURL(const char*, nsACString&, nsACString&, nsACString&, nsACString&, nsACString&);
+ nsresult GetErrorMessage(nsIURI*, const char*, char**, char**, char**, char**, char**, char**);
+ nsresult CreateErrorPage(nsIURI*, nsIChannel**);
+ nsresult CreateRecoverPage(nsIURI*, nsIChannel**);
+ nsresult WritePage(nsIURI*, nsIURI*, nsIURI*, const nsACString&, const char*, const char*, const char*, const char*, const char*, const char*, nsIChannel**);
+ nsresult Write(nsIOutputStream*, const char*);
+};
+
+#endif /* EPHY_ABOUT_MODULE_H */
diff --git a/embed/xulrunner/embed/EphyBadCertRejector.cpp b/embed/xulrunner/embed/EphyBadCertRejector.cpp
new file mode 100644
index 000000000..99ffe4393
--- /dev/null
+++ b/embed/xulrunner/embed/EphyBadCertRejector.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2005 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include "EphyBadCertRejector.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1 (EphyBadCertRejector, nsIBadCertListener)
+
+/* boolean confirmUnknownIssuer (in nsIInterfaceRequestor socketInfo, in nsIX509Cert cert, out short certAddType); */
+NS_IMETHODIMP
+EphyBadCertRejector::ConfirmUnknownIssuer(nsIInterfaceRequestor *socketInfo,
+ nsIX509Cert *cert,
+ PRInt16 *certAddType,
+ PRBool *_retval)
+{
+ *certAddType = nsIBadCertListener::UNINIT_ADD_FLAG;
+ *_retval = PR_FALSE;
+ return NS_OK;
+}
+
+/* boolean confirmMismatchDomain (in nsIInterfaceRequestor socketInfo, in AUTF8String targetURL, in nsIX509Cert cert); */
+NS_IMETHODIMP
+EphyBadCertRejector::ConfirmMismatchDomain(nsIInterfaceRequestor *socketInfo,
+ const nsACString & targetURL,
+ nsIX509Cert *cert,
+ PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+ return NS_OK;
+}
+
+/* boolean confirmCertExpired (in nsIInterfaceRequestor socketInfo, in nsIX509Cert cert); */
+NS_IMETHODIMP
+EphyBadCertRejector::ConfirmCertExpired(nsIInterfaceRequestor *socketInfo,
+ nsIX509Cert *cert,
+ PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+ return NS_OK;
+}
+
+/* void notifyCrlNextupdate (in nsIInterfaceRequestor socketInfo, in AUTF8String targetURL, in nsIX509Cert cert); */
+NS_IMETHODIMP
+EphyBadCertRejector::NotifyCrlNextupdate(nsIInterfaceRequestor *socketInfo,
+ const nsACString & targetURL,
+ nsIX509Cert *cert)
+{
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/EphyBadCertRejector.h b/embed/xulrunner/embed/EphyBadCertRejector.h
new file mode 100644
index 000000000..dcab75c6c
--- /dev/null
+++ b/embed/xulrunner/embed/EphyBadCertRejector.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2005 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_BAD_CERT_REJECTOR_H
+#define EPHY_BAD_CERT_REJECTOR_H
+
+#include <nsIBadCertListener.h>
+
+class EphyBadCertRejector : public nsIBadCertListener
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIBADCERTLISTENER
+
+ EphyBadCertRejector () { }
+ ~EphyBadCertRejector () { }
+};
+
+#endif
diff --git a/embed/xulrunner/embed/EphyBrowser.cpp b/embed/xulrunner/embed/EphyBrowser.cpp
new file mode 100644
index 000000000..f80aeb59a
--- /dev/null
+++ b/embed/xulrunner/embed/EphyBrowser.cpp
@@ -0,0 +1,1614 @@
+/*
+ * Copyright © 2000-2004 Marco Pesenti Gritti
+ * Copyright © 2003, 2004, 2005 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <unistd.h>
+
+#include <nsStringAPI.h>
+
+#include <nsIChannel.h>
+#include <nsICommandManager.h>
+#include <nsIContentViewer.h>
+#include <nsIDocCharset.h>
+#include <nsIDocShellTreeItem.h>
+#include <nsIDocShellTreeNode.h>
+#include <nsIDocShellTreeOwner.h>
+#include <nsIDOM3Document.h>
+#include <nsIDOMAbstractView.h>
+#include <nsIDOMAbstractView.h>
+#include <nsIDOMCSSPrimitiveValue.h>
+#include <nsIDOMCSSStyleDeclaration.h>
+#include <nsIDOMCSSStyleDeclaration.h>
+#include <nsIDOMCSSValue.h>
+#include <nsIDOMDocument.h>
+#include <nsIDOMDocumentView.h>
+#include <nsIDOMDocumentView.h>
+#include <nsIDOMElement.h>
+#include <nsIDOMEvent.h>
+#include <nsIDOMEventTarget.h>
+#include <nsIDOMHTMLCollection.h>
+#include <nsIDOMHTMLDocument.h>
+#include <nsIDOMHTMLDocument.h>
+#include <nsIDOMHTMLElement.h>
+#include <nsIDOMHTMLFormElement.h>
+#include <nsIDOMHTMLInputElement.h>
+#include <nsIDOMHTMLTextAreaElement.h>
+#include <nsIDOMKeyEvent.h>
+#include <nsIDOMMouseEvent.h>
+#include <nsIDOMNode.h>
+#include <nsIDOMNSEvent.h>
+#include <nsIDOMNSEventTarget.h>
+#include <nsIDOMPopupBlockedEvent.h>
+#include <nsIDOMViewCSS.h>
+#include <nsIDOMWindow2.h>
+#include <nsIDOMXMLDocument.h>
+#include <nsIHistoryEntry.h>
+#include <nsIInterfaceRequestor.h>
+#include <nsIInterfaceRequestorUtils.h>
+#include <nsIPrintSettings.h>
+#include <nsIPrintSettingsService.h>
+#include <nsIScriptSecurityManager.h>
+#include <nsIServiceManager.h>
+#include <nsISHEntry.h>
+#include <nsISHistory.h>
+#include <nsISHistoryInternal.h>
+#include <nsISimpleEnumerator.h>
+#include <nsIURI.h>
+#include <nsIWebBrowserFocus.h>
+#include <nsIWebBrowserPrint.h>
+#include <nsIWebPageDescriptor.h>
+#include <nsMemory.h>
+#include <nsServiceManagerUtils.h>
+
+#ifdef HAVE_MOZILLA_PSM
+#include <nsICertificateDialogs.h>
+#include <nsISSLStatus.h>
+#include <nsISSLStatusProvider.h>
+#include <nsITransportSecurityInfo.h>
+#include <nsIX509Cert.h>
+#endif
+
+#ifdef ALLOW_PRIVATE_API
+#include <nsIContentPolicy.h>
+#include <nsIDocShell.h>
+#include <nsIDOMWindowInternal.h>
+#include <nsIImageDocument.h>
+#include <nsIMarkupDocumentViewer.h>
+#endif
+
+#include "gecko-embed.h"
+#include "gecko-embed-private.h"
+
+#include "ephy-debug.h"
+#include "ephy-embed.h"
+#include "ephy-embed-shell.h"
+#include "ephy-string.h"
+#include "ephy-zoom.h"
+#include "mozilla-embed-event.h"
+#include "mozilla-embed.h"
+
+#include "AutoJSContextStack.h"
+#include "EphyUtils.h"
+#include "EventContext.h"
+#include "GeckoPrintService.h"
+
+#include "EphyBrowser.h"
+
+NS_IMPL_ISUPPORTS1(EphyEventListener, nsIDOMEventListener)
+
+NS_IMETHODIMP
+EphyDOMLinkEventListener::HandleEvent (nsIDOMEvent* aDOMEvent)
+{
+ nsCOMPtr<nsIDOMEventTarget> eventTarget;
+ aDOMEvent->GetTarget(getter_AddRefs(eventTarget));
+
+ nsCOMPtr<nsIDOMElement> linkElement (do_QueryInterface (eventTarget));
+ if (!linkElement) return NS_ERROR_FAILURE;
+
+ nsresult rv;
+ nsString value;
+ rv = linkElement->GetAttribute (NS_LITERAL_STRING ("rel"), value);
+ if (NS_FAILED (rv)) return NS_ERROR_FAILURE;
+
+ nsCString rel;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, rel);
+
+ if (g_ascii_strcasecmp (rel.get(), "SHORTCUT ICON") == 0 ||
+ g_ascii_strcasecmp (rel.get(), "ICON") == 0)
+ {
+ nsCOMPtr<nsIDOMDocument> domDoc;
+ linkElement->GetOwnerDocument(getter_AddRefs(domDoc));
+ NS_ENSURE_TRUE (domDoc, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDOMDocumentView> docView (do_QueryInterface (domDoc));
+ NS_ENSURE_TRUE (docView, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDOMAbstractView> abstractView;
+ docView->GetDefaultView (getter_AddRefs (abstractView));
+
+ nsCOMPtr<nsIDOMWindow> domWin (do_QueryInterface (abstractView));
+ NS_ENSURE_TRUE (domWin, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDOMWindow> topDomWin;
+ domWin->GetTop (getter_AddRefs (topDomWin));
+
+ nsCOMPtr<nsISupports> domWinAsISupports (do_QueryInterface (domWin));
+ nsCOMPtr<nsISupports> topDomWinAsISupports (do_QueryInterface (topDomWin));
+ /* disallow subframes to set favicon */
+ if (domWinAsISupports != topDomWinAsISupports) return NS_OK;
+
+ nsCOMPtr<nsIURI> docUri;
+ rv = GetDocURI (linkElement, getter_AddRefs (docUri));
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && docUri, NS_ERROR_FAILURE);
+
+ rv = linkElement->GetAttribute (NS_LITERAL_STRING ("href"), value);
+ if (NS_FAILED (rv) || !value.Length()) return NS_ERROR_FAILURE;
+
+ nsCString cLink;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cLink);
+
+ nsCString faviconUrl;
+ rv = docUri->Resolve (cLink, faviconUrl);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIURI> favUri;
+ EphyUtils::NewURI (getter_AddRefs (favUri), faviconUrl);
+ NS_ENSURE_TRUE (favUri, NS_ERROR_FAILURE);
+
+ /* Only proceed for http favicons. Bug #312291 */
+ PRBool isHttp = PR_FALSE, isHttps = PR_FALSE;
+ favUri->SchemeIs ("http", &isHttp);
+ favUri->SchemeIs ("https", &isHttps);
+ if (!isHttp && !isHttps) return NS_OK;
+
+ /* check if load is allowed */
+ nsCOMPtr<nsIScriptSecurityManager> secMan
+ (do_GetService("@mozilla.org/scriptsecuritymanager;1"));
+ /* refuse if we can't check */
+ NS_ENSURE_TRUE (secMan, NS_OK);
+
+ rv = secMan->CheckLoadURI(docUri, favUri,
+ nsIScriptSecurityManager::STANDARD);
+ /* failure means it didn't pass the security check */
+ if (NS_FAILED (rv)) return NS_OK;
+
+ /* security check passed, now check with content policy */
+ nsCOMPtr<nsIContentPolicy> policy =
+ do_GetService("@mozilla.org/layout/content-policy;1");
+ /* refuse if we can't check */
+ NS_ENSURE_TRUE (policy, NS_OK);
+
+ linkElement->GetAttribute (NS_LITERAL_STRING ("type"), value);
+
+ nsCString cTypeVal;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cTypeVal);
+
+ PRInt16 decision = 0;
+ rv = policy->ShouldLoad (nsIContentPolicy::TYPE_IMAGE,
+ favUri, docUri, eventTarget,
+ cTypeVal, nsnull,
+ &decision);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+ if (decision != nsIContentPolicy::ACCEPT) return NS_OK;
+
+ /* Hide password part */
+ nsCString user;
+ favUri->GetUsername (user);
+ favUri->SetUserPass (user);
+
+ nsCString spec;
+ favUri->GetSpec (spec);
+
+ /* ok, we accept this as a valid favicon for this site */
+ g_signal_emit_by_name (mOwner->mEmbed, "ge_favicon", spec.get());
+ }
+ else if (g_ascii_strcasecmp (rel.get (), "search") == 0)
+ {
+ linkElement->GetAttribute (NS_LITERAL_STRING ("type"), value);
+
+ nsCString cTypeVal;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cTypeVal);
+
+ if (g_ascii_strcasecmp (cTypeVal.get (),
+ "application/opensearchdescription+xml") == 0)
+ {
+ rv = linkElement->GetAttribute (NS_LITERAL_STRING ("href"), value);
+ if (NS_FAILED (rv) || !value.Length()) return NS_ERROR_FAILURE;
+
+ nsCString cLink;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cLink);
+
+ nsCOMPtr<nsIURI> docUri;
+ rv = GetDocURI (linkElement, getter_AddRefs (docUri));
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && docUri, NS_ERROR_FAILURE);
+
+ nsCString resolvedLink;
+ rv = docUri->Resolve (cLink, resolvedLink);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ linkElement->GetAttribute (NS_LITERAL_STRING ("title"), value);
+
+ nsCString cTitle;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cTitle);
+
+ g_signal_emit_by_name (mOwner->mEmbed, "ge_search_link",
+ cTypeVal.get(), cTitle.get(), resolvedLink.get());
+ }
+ }
+ else if (g_ascii_strcasecmp (rel.get (), "alternate") == 0)
+ {
+ linkElement->GetAttribute (NS_LITERAL_STRING ("type"), value);
+
+ nsCString cTypeVal;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cTypeVal);
+
+ if (g_ascii_strcasecmp (cTypeVal.get (), "application/rss+xml") == 0 ||
+ g_ascii_strcasecmp (cTypeVal.get (), "application/atom+xml") == 0)
+ {
+ rv = linkElement->GetAttribute (NS_LITERAL_STRING ("href"), value);
+ if (NS_FAILED (rv) || !value.Length()) return NS_ERROR_FAILURE;
+
+ nsCString cLink;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cLink);
+
+ nsCOMPtr<nsIURI> docUri;
+ rv = GetDocURI (linkElement, getter_AddRefs (docUri));
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && docUri, NS_ERROR_FAILURE);
+
+ /* Hide password part */
+ nsCString user;
+ docUri->GetUsername (user);
+ docUri->SetUserPass (user);
+
+ nsCString resolvedLink;
+ rv = docUri->Resolve (cLink, resolvedLink);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ linkElement->GetAttribute (NS_LITERAL_STRING ("title"), value);
+
+ nsCString cTitle;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cTitle);
+
+ g_signal_emit_by_name (mOwner->mEmbed, "ge_feed_link",
+ cTypeVal.get(), cTitle.get(), resolvedLink.get());
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EphyMiscDOMEventsListener::HandleEvent (nsIDOMEvent* aDOMEvent)
+{
+ /* make sure the event is trusted */
+ nsCOMPtr<nsIDOMNSEvent> nsEvent (do_QueryInterface (aDOMEvent));
+ NS_ENSURE_TRUE (nsEvent, NS_ERROR_FAILURE);
+ PRBool isTrusted = PR_FALSE;
+ nsEvent->GetIsTrusted (&isTrusted);
+ if (!isTrusted) return NS_OK;
+
+ nsresult rv;
+ nsString type;
+ rv = aDOMEvent->GetType (type);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCString cType;
+ NS_UTF16ToCString (type, NS_CSTRING_ENCODING_UTF8, cType);
+
+ if (g_ascii_strcasecmp (cType.get(), "DOMContentLoaded") == 0)
+ {
+ g_signal_emit_by_name (mOwner->mEmbed, "dom_content_loaded",
+ (gpointer)aDOMEvent);
+ }
+ else if (g_ascii_strcasecmp (cType.get(), "DOMWindowClose") == 0)
+ {
+ gboolean prevent = FALSE;
+
+ g_signal_emit_by_name (mOwner->mEmbed, "close-request", &prevent);
+
+ if (prevent)
+ {
+ aDOMEvent->PreventDefault ();
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult
+EphyDOMLinkEventListener::GetDocURI (nsIDOMElement *aElement,
+ nsIURI **aDocURI)
+{
+ nsCOMPtr<nsIDOMDocument> domDoc;
+ aElement->GetOwnerDocument (getter_AddRefs(domDoc));
+
+ nsCOMPtr<nsIDOM3Document> doc (do_QueryInterface (domDoc));
+ NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE);
+
+ nsresult rv;
+ nsString spec;
+ rv = doc->GetDocumentURI (spec);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCString encoding;
+ rv = mOwner->GetEncoding (encoding);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ return EphyUtils::NewURI (aDocURI, spec, encoding.get());
+}
+
+NS_IMETHODIMP
+EphyPopupBlockEventListener::HandleEvent (nsIDOMEvent * aDOMEvent)
+{
+ nsCOMPtr<nsIDOMPopupBlockedEvent> popupEvent =
+ do_QueryInterface (aDOMEvent);
+ NS_ENSURE_TRUE (popupEvent, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIURI> popupWindowURI;
+ popupEvent->GetPopupWindowURI (getter_AddRefs (popupWindowURI));
+
+ nsCString popupWindowURIString;
+ nsresult rv;
+
+ if (popupWindowURI)
+ {
+ rv = popupWindowURI->GetSpec (popupWindowURIString);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+ }
+
+ nsString popupWindowFeatures;
+ rv = popupEvent->GetPopupWindowFeatures (popupWindowFeatures);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ nsCString popupWindowFeaturesString;
+ NS_UTF16ToCString (popupWindowFeatures,
+ NS_CSTRING_ENCODING_UTF8,
+ popupWindowFeaturesString);
+
+ nsCString popupWindowNameString;
+#ifdef HAVE_GECKO_1_9
+ nsString popupWindowName;
+ rv = popupEvent->GetPopupWindowName (popupWindowName);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ NS_UTF16ToCString (popupWindowName,
+ NS_CSTRING_ENCODING_UTF8,
+ popupWindowNameString);
+#endif
+
+ g_signal_emit_by_name(mOwner->mEmbed, "ge-popup-blocked",
+ popupWindowURI == NULL ? NULL : popupWindowURIString.get(),
+ popupWindowNameString.get(),
+ popupWindowFeaturesString.get());
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EphyModalAlertEventListener::HandleEvent (nsIDOMEvent * aDOMEvent)
+{
+ NS_ENSURE_TRUE (mOwner, NS_ERROR_FAILURE);
+
+ nsresult rv;
+ nsString type;
+ rv = aDOMEvent->GetType (type);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCString cType;
+ NS_UTF16ToCString (type, NS_CSTRING_ENCODING_UTF8, cType);
+
+ LOG ("ModalAlertListener event %s", cType.get());
+
+ if (strcmp (cType.get(), "DOMWillOpenModalDialog") == 0)
+ {
+ gboolean retval = FALSE;
+ g_signal_emit_by_name (mOwner->mEmbed, "ge-modal-alert", &retval);
+
+ /* suppress alert */
+ if (retval)
+ {
+ aDOMEvent->PreventDefault ();
+ aDOMEvent->StopPropagation();
+ }
+ }
+ else if (strcmp (cType.get(), "DOMModalDialogClosed") == 0)
+ {
+ g_signal_emit_by_name (mOwner->mEmbed, "ge-modal-alert-closed");
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EphyDOMScrollEventListener::HandleEvent (nsIDOMEvent * aEvent)
+{
+ nsresult rv;
+ nsCOMPtr<nsIDOMMouseEvent> mouseEvent (do_QueryInterface (aEvent, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ PRBool isAlt = PR_FALSE, isControl = PR_FALSE, isShift = PR_FALSE;
+ mouseEvent->GetAltKey (&isAlt);
+ mouseEvent->GetCtrlKey (&isControl);
+ mouseEvent->GetShiftKey (&isShift);
+ /* GetMetaKey is always false on gtk2 mozilla */
+
+ if (isControl && !isAlt && !isShift)
+ {
+ PRInt32 detail = 0;
+ mouseEvent->GetDetail(&detail);
+
+ float zoom;
+ rv = mOwner->GetZoom (&zoom);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ zoom = ephy_zoom_get_changed_zoom_level (zoom, detail > 0 ? 1 : detail < 0 ? -1 : 0);
+ rv = mOwner->SetZoom (zoom);
+ if (NS_SUCCEEDED (rv))
+ {
+ g_signal_emit_by_name (mOwner->mEmbed, "ge_zoom_change", zoom);
+ }
+
+ /* we consumed the event */
+ aEvent->PreventDefault();
+ }
+
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS1(EphyContextMenuListener, nsIDOMContextMenuListener)
+
+NS_IMETHODIMP
+EphyContextMenuListener::ContextMenu (nsIDOMEvent* aDOMEvent)
+{
+ nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aDOMEvent);
+ NS_ENSURE_TRUE (mouseEvent, NS_ERROR_FAILURE);
+
+ MozillaEmbedEvent *info;
+ info = mozilla_embed_event_new (static_cast<gpointer>(aDOMEvent));
+
+ nsresult rv;
+ EventContext context;
+ context.Init (mOwner);
+ rv = context.GetMouseEventInfo (mouseEvent, MOZILLA_EMBED_EVENT (info));
+
+ /* Don't do any magic handling if we can't actually show the context
+ * menu, this can happen for XUL pages (e.g. about:config)
+ */
+ if (NS_FAILED (rv))
+ {
+ g_object_unref (info);
+ return NS_OK;
+ }
+
+ if (info->button == 0)
+ {
+ /* Translate relative coordinates to absolute values, and try
+ * to avoid covering links by adding a little offset
+ */
+ int x, y;
+ gdk_window_get_origin (GTK_WIDGET (mOwner->mEmbed)->window, &x, &y);
+ info->x += x + 6;
+ info->y += y + 6;
+
+ // Set the keycode to something sensible
+ info->keycode = nsIDOMKeyEvent::DOM_VK_CONTEXT_MENU;
+ }
+
+ if (info->modifier == GDK_CONTROL_MASK)
+ {
+ info->context = EPHY_EMBED_CONTEXT_DOCUMENT;
+ }
+
+ gboolean retval = FALSE;
+ nsCOMPtr<nsIDOMDocument> domDoc;
+ rv = context.GetTargetDocument (getter_AddRefs(domDoc));
+ if (NS_SUCCEEDED(rv))
+ {
+ mOwner->PushTargetDocument (domDoc);
+
+ g_signal_emit_by_name (mOwner->mEmbed, "ge_context_menu",
+ info, &retval);
+
+ mOwner->PopTargetDocument ();
+ }
+
+ /* We handled the event, block javascript calls */
+ if (retval)
+ {
+ aDOMEvent->PreventDefault();
+ aDOMEvent->StopPropagation();
+ }
+
+ g_object_unref (info);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EphyContextMenuListener::HandleEvent (nsIDOMEvent* aDOMEvent)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+EphyBrowser::EphyBrowser ()
+: mDOMLinkEventListener(nsnull)
+, mMiscDOMEventsListener(nsnull)
+, mDOMScrollEventListener(nsnull)
+, mPopupBlockEventListener(nsnull)
+, mModalAlertListener(nsnull)
+, mContextMenuListener(nsnull)
+, mInitialized(PR_FALSE)
+{
+ LOG ("EphyBrowser ctor (%p)", this);
+}
+
+EphyBrowser::~EphyBrowser ()
+{
+ LOG ("EphyBrowser dtor (%p)", this);
+}
+
+nsresult EphyBrowser::Init (GeckoEmbed *mozembed)
+{
+ if (mInitialized) return NS_OK;
+
+ mEmbed = GTK_WIDGET (mozembed);
+
+ gecko_embed_get_nsIWebBrowser (mozembed,
+ getter_AddRefs(mWebBrowser));
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ mWebBrowserFocus = do_QueryInterface (mWebBrowser);
+ NS_ENSURE_TRUE (mWebBrowserFocus, NS_ERROR_FAILURE);
+
+ mWebBrowser->GetContentDOMWindow (getter_AddRefs (mDOMWindow));
+ NS_ENSURE_TRUE (mDOMWindow, NS_ERROR_FAILURE);
+
+ /* This will instantiate an about:blank doc if necessary */
+ nsresult rv;
+ nsCOMPtr<nsIDOMDocument> domDocument;
+ rv = mDOMWindow->GetDocument (getter_AddRefs (domDocument));
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ mDOMLinkEventListener = new EphyDOMLinkEventListener(this);
+ if (!mDOMLinkEventListener) return NS_ERROR_OUT_OF_MEMORY;
+
+ mMiscDOMEventsListener = new EphyMiscDOMEventsListener(this);
+ if (!mMiscDOMEventsListener) return NS_ERROR_OUT_OF_MEMORY;
+
+ mDOMScrollEventListener = new EphyDOMScrollEventListener(this);
+ if (!mDOMScrollEventListener) return NS_ERROR_OUT_OF_MEMORY;
+
+ mPopupBlockEventListener = new EphyPopupBlockEventListener(this);
+ if (!mPopupBlockEventListener) return NS_ERROR_OUT_OF_MEMORY;
+
+ mModalAlertListener = new EphyModalAlertEventListener (this);
+ if (!mModalAlertListener) return NS_ERROR_OUT_OF_MEMORY;
+
+ mContextMenuListener = new EphyContextMenuListener(this);
+ if (!mContextMenuListener) return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = GetListener();
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ rv = AttachListeners();
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+#ifdef HAVE_MOZILLA_PSM
+ nsCOMPtr<nsIDocShell> docShell (do_GetInterface (mWebBrowser, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = docShell->GetSecurityUI (getter_AddRefs (mSecurityInfo));
+ if (!mSecurityInfo)
+ {
+ g_warning ("Failed to get nsISecureBrowserUI!\n");
+ }
+ NS_ENSURE_SUCCESS (rv, rv);
+#endif /* HAVE_MOZILLA_PSM */
+
+ mInitialized = PR_TRUE;
+
+ return NS_OK;
+}
+
+nsresult
+EphyBrowser::GetListener (void)
+{
+ if (mEventTarget) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIDOMWindow> domWindowExternal;
+ mWebBrowser->GetContentDOMWindow (getter_AddRefs(domWindowExternal));
+
+ nsCOMPtr<nsIDOMWindow2> domWindow (do_QueryInterface (domWindowExternal));
+ NS_ENSURE_TRUE (domWindow, NS_ERROR_FAILURE);
+
+ domWindow->GetWindowRoot (getter_AddRefs(mEventTarget));
+ NS_ENSURE_TRUE (mEventTarget, NS_ERROR_FAILURE);
+
+ return NS_OK;
+}
+
+nsresult
+EphyBrowser::AttachListeners(void)
+{
+ NS_ENSURE_TRUE (mEventTarget, NS_ERROR_FAILURE);
+
+ nsresult rv;
+ nsCOMPtr<nsIDOMNSEventTarget> target (do_QueryInterface (mEventTarget, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = target->AddEventListener(NS_LITERAL_STRING ("DOMLinkAdded"),
+ mDOMLinkEventListener, PR_FALSE, PR_FALSE);
+ rv |= target->AddEventListener(NS_LITERAL_STRING ("DOMContentLoaded"),
+ mMiscDOMEventsListener, PR_FALSE, PR_FALSE);
+ rv |= target->AddEventListener(NS_LITERAL_STRING ("DOMWindowClose"),
+ mMiscDOMEventsListener, PR_FALSE, PR_FALSE);
+ rv |= target->AddEventListener(NS_LITERAL_STRING ("DOMMouseScroll"),
+ mDOMScrollEventListener, PR_TRUE /* capture */, PR_FALSE);
+ rv |= target->AddEventListener(NS_LITERAL_STRING ("DOMPopupBlocked"),
+ mPopupBlockEventListener, PR_FALSE, PR_FALSE);
+ rv |= target->AddEventListener(NS_LITERAL_STRING ("DOMWillOpenModalDialog"),
+ mModalAlertListener, PR_TRUE, PR_FALSE);
+ rv |= target->AddEventListener(NS_LITERAL_STRING ("DOMModalDialogClosed"),
+ mModalAlertListener, PR_TRUE, PR_FALSE);
+ rv |= target->AddEventListener(NS_LITERAL_STRING ("contextmenu"),
+ mContextMenuListener, PR_TRUE /* capture */, PR_FALSE);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ return NS_OK;
+}
+
+nsresult
+EphyBrowser::DetachListeners(void)
+{
+ if (!mEventTarget) return NS_OK;
+
+ nsresult rv;
+ rv = mEventTarget->RemoveEventListener(NS_LITERAL_STRING ("DOMLinkAdded"),
+ mDOMLinkEventListener, PR_FALSE);
+ rv |= mEventTarget->RemoveEventListener(NS_LITERAL_STRING ("DOMContentLoaded"),
+ mMiscDOMEventsListener, PR_FALSE);
+ rv |= mEventTarget->RemoveEventListener(NS_LITERAL_STRING ("DOMWindowClose"),
+ mMiscDOMEventsListener, PR_FALSE);
+ rv |= mEventTarget->RemoveEventListener(NS_LITERAL_STRING ("DOMMouseScroll"),
+ mDOMScrollEventListener, PR_TRUE); /* capture */
+ rv |= mEventTarget->RemoveEventListener(NS_LITERAL_STRING ("DOMPopupBlocked"),
+ mPopupBlockEventListener, PR_FALSE);
+ rv |= mEventTarget->RemoveEventListener(NS_LITERAL_STRING ("DOMWillOpenModalDialog"),
+ mModalAlertListener, PR_TRUE);
+ rv |= mEventTarget->RemoveEventListener(NS_LITERAL_STRING ("DOMModalDialogClosed"),
+ mModalAlertListener, PR_TRUE);
+ rv |= mEventTarget->RemoveEventListener(NS_LITERAL_STRING ("contextmenu"),
+ mContextMenuListener, PR_TRUE /* capture */);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::Print ()
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(mWebBrowser));
+ NS_ENSURE_TRUE (print, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIPrintSettingsService> printSettingsService
+ (do_GetService("@mozilla.org/gfx/printsettings-service;1"));
+ NS_ENSURE_STATE (printSettingsService);
+
+ nsCOMPtr<nsIPrintSettings> settings;
+ printSettingsService->GetNewPrintSettings (getter_AddRefs (settings));
+ NS_ENSURE_STATE (settings);
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ return print->Print (settings, nsnull);
+}
+
+nsresult EphyBrowser::SetPrintPreviewMode (PRBool previewMode)
+{
+ nsresult rv;
+
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIWebBrowserPrint> print (do_GetInterface (mWebBrowser));
+ NS_ENSURE_STATE (print);
+
+ if (previewMode)
+ {
+ nsCOMPtr<nsIPrintSettingsService> printSettingsService
+ (do_GetService("@mozilla.org/gfx/printsettings-service;1"));
+ NS_ENSURE_STATE (printSettingsService);
+
+ nsCOMPtr<nsIPrintSettings> settings;
+ printSettingsService->GetNewPrintSettings (getter_AddRefs (settings));
+ NS_ENSURE_STATE (settings);
+
+ EphyEmbedShell *shell = ephy_embed_shell_get_default ();
+ rv = GeckoPrintService::TranslateSettings (ephy_embed_shell_get_print_settings (shell),
+ ephy_embed_shell_get_page_setup (shell),
+ NULL,
+ nsCString(),
+ nsIPrintSettings::kFramesAsIs,
+ PR_FALSE,
+ settings);
+
+ if (NS_SUCCEEDED (rv))
+ {
+ rv = print->PrintPreview (settings, mDOMWindow, nsnull);
+ }
+ }
+ else
+ {
+ PRBool isPreview = PR_FALSE;
+
+ rv = print->GetDoingPrintPreview(&isPreview);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ if (isPreview)
+ {
+ rv = print->ExitPrintPreview();
+ }
+ }
+
+ return rv;
+}
+
+nsresult EphyBrowser::PrintPreviewNumPages (int *numPages)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(mWebBrowser));
+ NS_ENSURE_TRUE (print, NS_ERROR_FAILURE);
+
+ return print->GetPrintPreviewNumPages(numPages);
+}
+
+nsresult EphyBrowser::PrintPreviewNavigate(PRInt16 navType, PRInt32 pageNum)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(mWebBrowser));
+ NS_ENSURE_TRUE (print, NS_ERROR_FAILURE);
+
+ return print->PrintPreviewNavigate(navType, pageNum);
+}
+
+nsresult EphyBrowser::GetSHistory (nsISHistory **aSHistory)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIWebNavigation> ContentNav = do_QueryInterface (mWebBrowser);
+ NS_ENSURE_TRUE (ContentNav, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsISHistory> SessionHistory;
+ ContentNav->GetSessionHistory (getter_AddRefs (SessionHistory));
+ NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE);
+
+ *aSHistory = SessionHistory.get();
+ NS_IF_ADDREF (*aSHistory);
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::CopySHistory (EphyBrowser *dest, PRBool copy_back,
+ PRBool copy_forward, PRBool copy_current)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsISHistory> h_src;
+ GetSHistory (getter_AddRefs(h_src));
+ NS_ENSURE_TRUE (h_src, NS_ERROR_FAILURE);
+
+ PRInt32 count, index;
+ h_src->GetCount (&count);
+ h_src->GetIndex (&index);
+
+ nsCOMPtr<nsISHistory> h_dest;
+ dest->GetSHistory (getter_AddRefs (h_dest));
+ NS_ENSURE_TRUE (h_dest, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsISHistoryInternal> hi_dest = do_QueryInterface (h_dest);
+ NS_ENSURE_TRUE (hi_dest, NS_ERROR_FAILURE);
+
+ if (count)
+ {
+ nsCOMPtr<nsIHistoryEntry> he;
+ nsCOMPtr<nsISHEntry> she, dhe;
+
+ for (PRInt32 i = (copy_back ? 0 : index + 1);
+ i < (copy_forward ? count : index + 1);
+ i++)
+ {
+ rv = h_src->GetEntryAtIndex (i, PR_FALSE,
+ getter_AddRefs (he));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ she = do_QueryInterface (he);
+ NS_ENSURE_TRUE (she, NS_ERROR_FAILURE);
+
+ rv = she->Clone(getter_AddRefs (dhe));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = hi_dest->AddEntry (dhe, PR_TRUE);
+ NS_ENSURE_SUCCESS (rv, rv);
+ }
+
+ if (copy_current)
+ {
+ nsCOMPtr<nsIWebNavigation> wn_dest = do_QueryInterface (dest->mWebBrowser);
+ NS_ENSURE_TRUE (wn_dest, NS_ERROR_FAILURE);
+
+ rv = wn_dest->GotoIndex(index);
+ if (!NS_SUCCEEDED(rv)) return NS_ERROR_FAILURE;
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::Destroy ()
+{
+ DetachListeners ();
+
+ mWebBrowser = nsnull;
+ mDOMWindow = nsnull;
+ mEventTarget = nsnull;
+ mEmbed = nsnull;
+
+ mInitialized = PR_FALSE;
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::GoToHistoryIndex (PRInt16 index)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIWebNavigation> ContentNav = do_QueryInterface (mWebBrowser);
+ NS_ENSURE_TRUE (ContentNav, NS_ERROR_FAILURE);
+
+ return ContentNav->GotoIndex (index);
+}
+
+nsresult EphyBrowser::SetZoom (float aZoom)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIContentViewer> contentViewer;
+ GetContentViewer (getter_AddRefs(contentViewer));
+ NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer);
+ NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE);
+
+ return mdv->SetTextZoom (aZoom);
+}
+
+nsresult EphyBrowser::GetContentViewer (nsIContentViewer **aViewer)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDocShell> ourDocShell(do_GetInterface(mWebBrowser));
+ NS_ENSURE_TRUE (ourDocShell, NS_ERROR_FAILURE);
+
+ return ourDocShell->GetContentViewer(aViewer);
+}
+
+nsresult EphyBrowser::GetZoom (float *aZoom)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIContentViewer> contentViewer;
+ GetContentViewer (getter_AddRefs(contentViewer));
+ NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer);
+ NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE);
+
+ return mdv->GetTextZoom (aZoom);
+}
+
+nsresult
+EphyBrowser::ScrollLines (PRInt32 aNumLines)
+{
+ nsCOMPtr<nsIDOMWindow> DOMWindow;
+
+ mWebBrowserFocus->GetFocusedWindow (getter_AddRefs(DOMWindow));
+ if (!DOMWindow)
+ {
+ DOMWindow = mDOMWindow;
+ }
+ NS_ENSURE_TRUE (DOMWindow, NS_ERROR_FAILURE);
+
+ return DOMWindow->ScrollByLines (aNumLines);
+}
+
+nsresult
+EphyBrowser::ScrollPages (PRInt32 aNumPages)
+{
+ nsCOMPtr<nsIDOMWindow> DOMWindow;
+
+ mWebBrowserFocus->GetFocusedWindow (getter_AddRefs(DOMWindow));
+ if (!DOMWindow)
+ {
+ DOMWindow = mDOMWindow;
+ }
+ NS_ENSURE_TRUE (DOMWindow, NS_ERROR_FAILURE);
+
+ return DOMWindow->ScrollByPages (aNumPages);
+}
+
+nsresult
+EphyBrowser::ScrollPixels (PRInt32 aDeltaX,
+ PRInt32 aDeltaY)
+{
+ nsCOMPtr<nsIDOMWindow> DOMWindow;
+
+ mWebBrowserFocus->GetFocusedWindow (getter_AddRefs(DOMWindow));
+ if (!DOMWindow)
+ {
+ DOMWindow = mDOMWindow;
+ }
+ NS_ENSURE_TRUE (DOMWindow, NS_ERROR_FAILURE);
+
+ return DOMWindow->ScrollBy (aDeltaX, aDeltaY);
+}
+
+nsresult
+EphyBrowser::GetDocument (nsIDOMDocument **aDOMDocument)
+{
+ return mDOMWindow->GetDocument (aDOMDocument);
+}
+
+nsresult
+EphyBrowser::GetTargetDocument (nsIDOMDocument **aDOMDocument)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ /* Use the current target document */
+ if (mTargetDocument)
+ {
+ *aDOMDocument = mTargetDocument.get();
+
+ NS_IF_ADDREF(*aDOMDocument);
+
+ return NS_OK;
+ }
+
+ /* Use the focused document */
+ nsresult rv;
+ nsCOMPtr<nsIDOMWindow> DOMWindow;
+ rv = mWebBrowserFocus->GetFocusedWindow (getter_AddRefs(DOMWindow));
+ if (NS_SUCCEEDED (rv) && DOMWindow)
+ {
+ return DOMWindow->GetDocument (aDOMDocument);
+ }
+
+ /* Use the main document */
+ return mDOMWindow->GetDocument (aDOMDocument);
+}
+
+nsresult EphyBrowser::GetSHInfo (PRInt32 *count, PRInt32 *index)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsISHistory> SessionHistory;
+ GetSHistory (getter_AddRefs(SessionHistory));
+ NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE);
+
+ SessionHistory->GetCount (count);
+ SessionHistory->GetIndex (index);
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::GetSHTitleAtIndex (PRInt32 index, PRUnichar **title)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsISHistory> SessionHistory;
+ GetSHistory (getter_AddRefs(SessionHistory));
+ NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIHistoryEntry> he;
+ SessionHistory->GetEntryAtIndex (index, PR_FALSE,
+ getter_AddRefs (he));
+ NS_ENSURE_TRUE (he, NS_ERROR_FAILURE);
+
+ nsresult rv;
+ rv = he->GetTitle (title);
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && title, NS_ERROR_FAILURE);
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::GetSHUrlAtIndex (PRInt32 index, nsACString &url)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsISHistory> SessionHistory;
+ GetSHistory (getter_AddRefs(SessionHistory));
+ NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIHistoryEntry> he;
+ SessionHistory->GetEntryAtIndex (index, PR_FALSE,
+ getter_AddRefs (he));
+ NS_ENSURE_TRUE (he, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIURI> uri;
+ he->GetURI (getter_AddRefs(uri));
+ NS_ENSURE_TRUE (uri, NS_ERROR_FAILURE);
+
+ nsresult rv;
+ rv = uri->GetSpec(url);
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && url.Length(), NS_ERROR_FAILURE);
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::GetPageDescriptor(nsISupports **aPageDescriptor)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDocShell> ds = do_GetInterface (mWebBrowser);
+
+ nsCOMPtr<nsIWebPageDescriptor> wpd = do_QueryInterface (ds);
+ NS_ENSURE_TRUE (wpd, NS_ERROR_FAILURE);
+
+ *aPageDescriptor = wpd.get();
+ NS_IF_ADDREF (*aPageDescriptor);
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::GetDOMWindow (nsIDOMWindow **aDOMWindow)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ NS_IF_ADDREF (*aDOMWindow = mDOMWindow);
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::GetDocumentURI (nsIURI **aURI)
+{
+ if (!mDOMWindow) return NS_ERROR_NOT_INITIALIZED;
+
+ nsresult rv;
+ nsCOMPtr<nsIWebNavigation> webNav (do_GetInterface (mDOMWindow, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ return webNav->GetCurrentURI (aURI);
+}
+
+nsresult EphyBrowser::GetTargetDocumentURI (nsIURI **aURI)
+{
+ if (!mWebBrowser) return NS_ERROR_NOT_INITIALIZED;
+
+ nsCOMPtr<nsIDOMDocument> domDoc;
+ GetTargetDocument (getter_AddRefs(domDoc));
+ NS_ENSURE_TRUE (domDoc, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDOMDocumentView> docView (do_QueryInterface (domDoc));
+ NS_ENSURE_TRUE (docView, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDOMAbstractView> abstractView;
+ docView->GetDefaultView (getter_AddRefs (abstractView));
+ NS_ENSURE_TRUE (abstractView, NS_ERROR_FAILURE);
+ /* the abstract view is really the DOM window */
+
+ nsresult rv;
+ nsCOMPtr<nsIWebNavigation> webNav (do_GetInterface (abstractView, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ return webNav->GetCurrentURI (aURI);
+}
+
+nsresult EphyBrowser::ForceEncoding (const char *encoding)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIContentViewer> contentViewer;
+ GetContentViewer (getter_AddRefs(contentViewer));
+ NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer);
+ NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE);
+
+ return mdv->SetForceCharacterSet (nsCString(encoding));
+}
+
+nsresult EphyBrowser::GetEncoding (nsACString &encoding)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDocCharset> docCharset = do_GetInterface (mWebBrowser);
+ NS_ENSURE_TRUE (docCharset, NS_ERROR_FAILURE);
+
+ char *charset;
+ docCharset->GetCharset (&charset);
+ encoding = charset;
+ nsMemory::Free (charset);
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::GetForcedEncoding (nsACString &encoding)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIContentViewer> contentViewer;
+ GetContentViewer (getter_AddRefs(contentViewer));
+ NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer);
+ NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE);
+
+ nsresult rv;
+ rv = mdv->GetForceCharacterSet (encoding);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::PushTargetDocument (nsIDOMDocument *domDoc)
+{
+ mTargetDocument = domDoc;
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::PopTargetDocument ()
+{
+ mTargetDocument = nsnull;
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::DoCommand (const char *command)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsICommandManager> cmdManager;
+ cmdManager = do_GetInterface (mWebBrowser);
+ NS_ENSURE_TRUE (cmdManager, NS_ERROR_FAILURE);
+
+ return cmdManager->DoCommand (command, nsnull, nsnull);
+}
+
+nsresult EphyBrowser::GetCommandState (const char *command, PRBool *enabled)
+{
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsICommandManager> cmdManager;
+ cmdManager = do_GetInterface (mWebBrowser);
+ NS_ENSURE_TRUE (cmdManager, NS_ERROR_FAILURE);
+
+ return cmdManager->IsCommandEnabled (command, nsnull, enabled);
+}
+
+#define NUM_MODIFIED_TEXTFIELDS_REQUIRED 2
+
+PRBool
+EphyBrowser::CompareFormsText (nsAString &aDefaultText, nsAString &aUserText)
+{
+ if (aDefaultText.Length() != aUserText.Length())
+ {
+ return FALSE;
+ }
+
+ /* Mozilla Bug 218277, 195946 and others */
+ const PRUnichar *text = aDefaultText.BeginReading();
+ for (PRUint32 i = 0; i < aDefaultText.Length(); i++)
+ {
+ if (text[i] == 0xa0)
+ {
+ aDefaultText.Replace (i, 1, ' ');
+ }
+ }
+
+ return (memcmp (aDefaultText.BeginReading(),
+ aUserText.BeginReading(),
+ aUserText.Length() * sizeof (PRUnichar)) == 0);
+}
+
+nsresult EphyBrowser::GetDocumentHasModifiedForms (nsIDOMDocument *aDomDoc, PRUint32 *aNumTextFields, PRBool *aHasTextArea)
+{
+ nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(aDomDoc);
+ /* it's okay not to be a HTML doc (happens for XUL documents, like about:config) */
+ if (!htmlDoc) return NS_OK;
+
+ nsCOMPtr<nsIDOMHTMLCollection> forms;
+ htmlDoc->GetForms (getter_AddRefs (forms));
+ if (!forms) return NS_OK; /* it's ok not to have any forms */
+
+ nsCOMPtr<nsIDOMDocumentView> docView (do_QueryInterface (aDomDoc));
+ nsCOMPtr<nsIDOMViewCSS> defaultCSSView;
+ if (docView)
+ {
+ nsCOMPtr<nsIDOMAbstractView> defaultView;
+ docView->GetDefaultView (getter_AddRefs (defaultView));
+ defaultCSSView = do_QueryInterface (defaultView);
+ }
+
+ const PRUnichar visibilityLiteral[] = { 'v', 'i', 's', 'i', 'b', 'i', 'l', 'i', 't', 'y', '\0' };
+ const PRUnichar visibleLiteral[] = { 'v', 'i', 's', 'i', 'b', 'l', 'e', '\0' };
+ nsString visibilityAttr(visibilityLiteral);
+ nsString visibleAttr(visibleLiteral);
+ nsString EmptyString;
+ nsCOMPtr<nsIDOMCSSStyleDeclaration> computedStyle;
+ nsCOMPtr<nsIDOMCSSValue> cssValue;
+ nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
+
+ PRUint32 formNum;
+ forms->GetLength (&formNum);
+
+ /* check all forms */
+ for (PRUint32 formIndex = 0; formIndex < formNum; formIndex++)
+ {
+ nsCOMPtr<nsIDOMNode> formNode;
+ forms->Item (formIndex, getter_AddRefs (formNode));
+ if (!formNode) continue;
+
+ nsCOMPtr<nsIDOMHTMLFormElement> formElement = do_QueryInterface (formNode);
+ if (!formElement) continue;
+
+ PRBool isVisible = PR_FALSE;
+ nsresult rv;
+ computedStyle = nsnull;
+
+ /* Check defaultCSSView for NULL, see bug #327764 */
+ if (defaultCSSView &&
+ NS_SUCCEEDED (defaultCSSView->GetComputedStyle (formElement, EmptyString,
+ getter_AddRefs (computedStyle))) &&
+ computedStyle)
+ {
+ rv = computedStyle->GetPropertyCSSValue(visibilityAttr, getter_AddRefs (cssValue));
+ if (NS_SUCCEEDED (rv) && cssValue)
+ {
+ nsString value;
+ rv = cssValue->GetCssText (value);
+ if (NS_SUCCEEDED (rv) && value.Length ())
+ {
+ /* what to do for "collapse" and "inherit" values? */
+ isVisible = CompareFormsText (value, visibleAttr);
+ }
+ }
+ }
+
+ if (!isVisible)
+ {
+ LOG ("Form node %p is invisible\n", formNode.get());
+ continue;
+ }
+
+ nsCOMPtr<nsIDOMHTMLCollection> formElements;
+ formElement->GetElements (getter_AddRefs (formElements));
+ if (!formElements) continue;
+
+ PRUint32 elementNum;
+ formElements->GetLength (&elementNum);
+
+ /* check all input elements in the form for user input */
+ for (PRUint32 elementIndex = 0; elementIndex < elementNum; elementIndex++)
+ {
+ nsCOMPtr<nsIDOMNode> domNode;
+ formElements->Item (elementIndex, getter_AddRefs (domNode));
+ if (!domNode) continue;
+
+ nsCOMPtr<nsIDOMElement> domElement (do_QueryInterface (domNode));
+ if (!domElement) continue;
+
+ isVisible = PR_FALSE;
+ computedStyle = nsnull;
+ /* Check defaultCSSView for NULL, see bug #327764 */
+ if (defaultCSSView &&
+ NS_SUCCEEDED (defaultCSSView->GetComputedStyle (domElement, EmptyString,
+ getter_AddRefs (computedStyle))) &&
+ computedStyle)
+ {
+ rv = computedStyle->GetPropertyCSSValue(visibilityAttr, getter_AddRefs (cssValue));
+ if (NS_SUCCEEDED (rv) && cssValue)
+ {
+ nsString value;
+ rv = cssValue->GetCssText (value);
+ if (NS_SUCCEEDED (rv) && value.Length ())
+ {
+ /* what to do for "collapse" and "inherit" values? */
+ isVisible = CompareFormsText (value, visibleAttr);
+ }
+ }
+ }
+
+ if (!isVisible)
+ {
+ LOG("Form node %p element %p is invisible\n", formNode.get(), domNode.get());
+ continue;
+ }
+
+ nsCOMPtr<nsIDOMHTMLTextAreaElement> areaElement = do_QueryInterface (domNode);
+ if (areaElement)
+ {
+ PRBool isDisabled = PR_TRUE;
+ areaElement->GetDisabled (&isDisabled);
+ if (isDisabled)
+ {
+ LOG ("Form node %p element %p [textarea] is disabled\n", formNode.get(), areaElement.get());
+ continue;
+ }
+
+ nsString defaultText, userText;
+ areaElement->GetDefaultValue (defaultText);
+ areaElement->GetValue (userText);
+
+ if (!CompareFormsText (defaultText, userText))
+ {
+ *aHasTextArea = PR_TRUE;
+ return NS_OK;
+ }
+
+ continue;
+ }
+
+ nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(domNode);
+ if (!inputElement) continue;
+
+ PRBool isDisabled = PR_TRUE;
+ inputElement->GetDisabled (&isDisabled);
+ if (isDisabled)
+ {
+ LOG ("Form node %p element %p [input] is disabled\n", formNode.get(), inputElement.get());
+ continue;
+ }
+
+ nsString type;
+ inputElement->GetType(type);
+
+ nsCString cType;
+ NS_UTF16ToCString (type, NS_CSTRING_ENCODING_UTF8, cType);
+
+ if (g_ascii_strcasecmp (cType.get(), "text") == 0)
+ {
+ nsString defaultText, userText;
+ PRInt32 max_length;
+ inputElement->GetDefaultValue (defaultText);
+ inputElement->GetValue (userText);
+ inputElement->GetMaxLength (&max_length);
+
+ /* There are forms for which defaultValue is longer than
+ * userValue. Mozilla consider this not a bug [see WONTFIXed
+ * bug 232057], but we need to check for this here.
+ */
+ if (defaultText.Length() > (PRUint32)max_length)
+ {
+ defaultText.Cut (max_length, PR_UINT32_MAX);
+ }
+
+ if (!CompareFormsText (defaultText, userText))
+ {
+ (*aNumTextFields)++;
+ if (*aNumTextFields >= NUM_MODIFIED_TEXTFIELDS_REQUIRED)
+ {
+ return NS_OK;
+ }
+ }
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult EphyBrowser::GetHasModifiedForms (PRBool *modified)
+{
+ *modified = PR_FALSE;
+
+ NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDocShell> rootDocShell = do_GetInterface (mWebBrowser);
+ NS_ENSURE_TRUE (rootDocShell, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsISimpleEnumerator> enumerator;
+ rootDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent,
+ nsIDocShell::ENUMERATE_FORWARDS,
+ getter_AddRefs(enumerator));
+ NS_ENSURE_TRUE (enumerator, NS_ERROR_FAILURE);
+
+ PRBool hasMore;
+ PRBool hasTextArea = PR_FALSE;
+ PRUint32 numTextFields = 0;
+ while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore)
+ {
+ nsCOMPtr<nsISupports> element;
+ enumerator->GetNext (getter_AddRefs(element));
+ if (!element) continue;
+
+ nsCOMPtr<nsIDocShell> docShell = do_QueryInterface (element);
+ if (!docShell) continue;
+
+ nsCOMPtr<nsIContentViewer> contentViewer;
+ docShell->GetContentViewer (getter_AddRefs(contentViewer));
+ if (!contentViewer) continue;
+
+ nsCOMPtr<nsIDOMDocument> domDoc;
+ contentViewer->GetDOMDocument (getter_AddRefs (domDoc));
+
+ nsresult rv;
+ rv = GetDocumentHasModifiedForms (domDoc, &numTextFields, &hasTextArea);
+ if (NS_SUCCEEDED (rv) &&
+ (numTextFields >= NUM_MODIFIED_TEXTFIELDS_REQUIRED || hasTextArea))
+ {
+ *modified = PR_TRUE;
+ break;
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult
+EphyBrowser::GetSecurityInfo (PRUint32 *aState, nsACString &aDescription)
+{
+#ifdef HAVE_MOZILLA_PSM
+ NS_ENSURE_TRUE (mSecurityInfo, NS_ERROR_FAILURE);
+
+ nsresult rv;
+ rv = mSecurityInfo->GetState (aState);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ nsString tooltip;
+ rv = mSecurityInfo->GetTooltipText (tooltip);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ NS_UTF16ToCString (tooltip,
+ NS_CSTRING_ENCODING_UTF8, aDescription);
+
+ return NS_OK;
+#else
+ return NS_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
+nsresult
+EphyBrowser::ShowCertificate ()
+{
+#ifdef HAVE_MOZILLA_PSM
+ NS_ENSURE_TRUE (mSecurityInfo, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsISSLStatusProvider> statusProvider (do_QueryInterface (mSecurityInfo));
+ NS_ENSURE_TRUE (statusProvider, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsISSLStatus> SSLStatus;
+ statusProvider->GetSSLStatus (getter_AddRefs (SSLStatus));
+ NS_ENSURE_TRUE (SSLStatus, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIX509Cert> serverCert;
+ SSLStatus->GetServerCert (getter_AddRefs (serverCert));
+ NS_ENSURE_TRUE (serverCert, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsICertificateDialogs> certDialogs (do_GetService (NS_CERTIFICATEDIALOGS_CONTRACTID));
+ NS_ENSURE_TRUE (certDialogs, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIInterfaceRequestor> requestor(do_QueryInterface (mDOMWindow));
+
+ return certDialogs->ViewCert (requestor, serverCert);
+#else
+ return NS_OK;
+#endif
+}
+
+EphyEmbedDocumentType
+EphyBrowser::GetDocumentType ()
+{
+ EphyEmbedDocumentType type = EPHY_EMBED_DOCUMENT_OTHER;
+
+ NS_ENSURE_TRUE (mDOMWindow, type);
+
+ nsresult rv;
+ nsCOMPtr<nsIDOMDocument> domDoc;
+ rv = GetDocument (getter_AddRefs (domDoc));
+ NS_ENSURE_SUCCESS (rv, type);
+
+ nsCOMPtr<nsIDOMHTMLDocument> htmlDoc (do_QueryInterface (domDoc));
+ nsCOMPtr<nsIDOMXMLDocument> xmlDoc (do_QueryInterface (domDoc));
+ nsCOMPtr<nsIImageDocument> imgDoc (do_QueryInterface (domDoc));
+
+ if (xmlDoc)
+ {
+ type = EPHY_EMBED_DOCUMENT_XML;
+ }
+ else if (imgDoc)
+ {
+ type = EPHY_EMBED_DOCUMENT_IMAGE;
+ }
+ else if (htmlDoc)
+ {
+ type = EPHY_EMBED_DOCUMENT_HTML;
+ }
+
+ return type;
+}
+
+nsresult
+EphyBrowser::Close ()
+{
+ nsCOMPtr<nsIDOMWindowInternal> domWin (do_QueryInterface (mDOMWindow));
+ NS_ENSURE_TRUE (domWin, NS_ERROR_FAILURE);
+
+ return domWin->Close();
+}
+
+nsresult
+EphyBrowser::GetPIDOMWindow(nsPIDOMWindow **aPIWin)
+{
+ *aPIWin = nsnull;
+
+ // get the private DOM window
+ nsCOMPtr<nsPIDOMWindow> domWindowPrivate = do_QueryInterface(mDOMWindow);
+
+ // and the root window for that DOM window
+ *aPIWin = domWindowPrivate->GetPrivateRoot();
+
+ if (*aPIWin)
+ {
+ NS_ADDREF(*aPIWin);
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+
+}
+
+nsresult
+EphyBrowser::LoadURI(const char *aURI,
+ PRUint32 aLoadFlags,
+ nsIURI *aReferrer)
+{
+ nsString uURI;
+ nsresult rv = NS_OK;
+
+ NS_CStringToUTF16 (nsCString (aURI), NS_CSTRING_ENCODING_UTF8, uURI);
+
+ if (uURI.Length() == 0) return NS_OK;
+
+ nsCOMPtr<nsIWebNavigation> contentNav = do_QueryInterface (mWebBrowser);
+ NS_ENSURE_TRUE (contentNav, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsPIDOMWindow> piWin;
+ rv = GetPIDOMWindow(getter_AddRefs(piWin));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsAutoPopupStatePusher popupStatePusher(piWin, openAllowed);
+
+ rv = contentNav->LoadURI(uURI.get(), // URI string
+ aLoadFlags, // Load flags
+ aReferrer, // Referring URI
+ nsnull, // Post data
+ nsnull); // extra headers
+
+ return rv;
+}
+
diff --git a/embed/xulrunner/embed/EphyBrowser.h b/embed/xulrunner/embed/EphyBrowser.h
new file mode 100644
index 000000000..1f23d2a73
--- /dev/null
+++ b/embed/xulrunner/embed/EphyBrowser.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright © 2000-2004 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_BROWSER_H
+#define EPHY_BROWSER_H
+
+#include "ephy-embed.h"
+#include <gtk/gtkwidget.h>
+
+#include <nsCOMPtr.h>
+#include <nsIDOMContextMenuListener.h>
+#include <nsIDOMDocument.h>
+#include <nsIDOMEventListener.h>
+#include <nsIDOMEventTarget.h>
+#include <nsIDOMWindow.h>
+#include <nsIRequest.h>
+#include <nsISHistory.h>
+#include <nsIWebBrowserFocus.h>
+#include <nsIWebBrowser.h>
+#include <nsIWebNavigation.h>
+#include <nsPIDOMWindow.h>
+
+#ifdef ALLOW_PRIVATE_API
+#include <nsIContentViewer.h>
+#endif
+
+#ifdef HAVE_MOZILLA_PSM
+#include <nsISecureBrowserUI.h>
+#endif
+
+#include "gecko-embed.h"
+
+class EphyBrowser;
+
+class EphyEventListener : public nsIDOMEventListener
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // nsIDOMEventListener
+ NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) = 0;
+
+ EphyEventListener(EphyBrowser *aOwner) : mOwner(aOwner) { };
+ virtual ~EphyEventListener() { };
+
+protected:
+ EphyBrowser *mOwner;
+};
+
+class EphyDOMLinkEventListener : public EphyEventListener
+{
+public:
+ NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
+
+ EphyDOMLinkEventListener(EphyBrowser *aOwner) : EphyEventListener(aOwner) { };
+private:
+ nsresult GetDocURI (nsIDOMElement *aElement,
+ nsIURI **aDocURI);
+
+};
+
+class EphyPopupBlockEventListener : public EphyEventListener
+{
+public:
+ NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
+
+ EphyPopupBlockEventListener(EphyBrowser *aOwner) : EphyEventListener(aOwner) { };
+};
+
+class EphyModalAlertEventListener : public EphyEventListener
+{
+public:
+ NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
+
+ EphyModalAlertEventListener(EphyBrowser *aOwner) : EphyEventListener(aOwner) { };
+};
+
+class EphyMiscDOMEventsListener : public EphyEventListener
+{
+public:
+ NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
+
+ EphyMiscDOMEventsListener(EphyBrowser *aOwner) : EphyEventListener(aOwner) { };
+};
+
+class EphyDOMScrollEventListener : public EphyEventListener
+{
+public:
+ NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
+
+ EphyDOMScrollEventListener(EphyBrowser *aOwner) : EphyEventListener(aOwner) { };
+};
+
+class EphyContextMenuListener : public nsIDOMContextMenuListener
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // nsIDOMContextMenuListener
+ NS_IMETHOD ContextMenu(nsIDOMEvent *aEvent);
+ NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
+
+ EphyContextMenuListener(EphyBrowser *aOwner) : mOwner(aOwner) { };
+ virtual ~EphyContextMenuListener() { };
+
+protected:
+ EphyBrowser *mOwner;
+};
+
+class EphyBrowser
+{
+friend class EphyEventListener;
+friend class EphyDOMLinkEventListener;
+friend class EphyMiscDOMEventsListener;
+friend class EphyDOMScrollEventListener;
+friend class EphyPopupBlockEventListener;
+friend class EphyModalAlertEventListener;
+friend class EphyContextMenuListener;
+public:
+ EphyBrowser();
+ ~EphyBrowser();
+
+ nsresult Init (GeckoEmbed *mozembed);
+ nsresult Destroy (void);
+
+ nsresult DoCommand (const char *command);
+ nsresult GetCommandState (const char *command, PRBool *enabled);
+
+ nsresult SetZoom (float aTextZoom);
+ nsresult GetZoom (float *aTextZoom);
+
+ nsresult ScrollLines (PRInt32 aNumLines);
+ nsresult ScrollPages (PRInt32 aNumPages);
+ nsresult ScrollPixels (PRInt32 aDeltaX, PRInt32 aDeltaY);
+
+ nsresult Print ();
+ nsresult SetPrintPreviewMode (PRBool previewMode);
+ nsresult PrintPreviewNumPages (int *numPages);
+ nsresult PrintPreviewNavigate(PRInt16 navType, PRInt32 pageNum);
+
+ nsresult GetPageDescriptor(nsISupports **aPageDescriptor);
+
+ nsresult GetSHInfo (PRInt32 *count, PRInt32 *index);
+ nsresult GetSHTitleAtIndex (PRInt32 index, PRUnichar **title);
+ nsresult GetSHUrlAtIndex (PRInt32 index, nsACString &url);
+ nsresult GoToHistoryIndex (PRInt16 index);
+
+ nsresult ForceEncoding (const char *encoding);
+ nsresult GetEncoding (nsACString &encoding);
+ nsresult GetForcedEncoding (nsACString &encoding);
+
+ nsresult PushTargetDocument (nsIDOMDocument *domDoc);
+ nsresult PopTargetDocument ();
+
+ nsresult GetDocument (nsIDOMDocument **aDOMDocument);
+ nsresult GetTargetDocument (nsIDOMDocument **aDOMDocument);
+ nsresult GetDocumentURI (nsIURI **aURI);
+ nsresult GetTargetDocumentURI (nsIURI **aURI);
+ nsresult GetDOMWindow (nsIDOMWindow **window);
+ nsresult GetPIDOMWindow(nsPIDOMWindow **aPIWin);
+
+ nsresult GetHasModifiedForms (PRBool *modified);
+
+ nsresult GetSecurityInfo (PRUint32 *aState, nsACString &aDescription);
+ nsresult ShowCertificate ();
+
+ nsresult CopySHistory (EphyBrowser *dest, PRBool copy_back,
+ PRBool copy_forward, PRBool copy_current);
+
+ nsresult Close ();
+
+ nsresult LoadURI(const char *aURI,
+ PRUint32 aLoadFlags = nsIWebNavigation::LOAD_FLAGS_NONE,
+ nsIURI *aURI = nsnull);
+
+ EphyEmbedDocumentType GetDocumentType ();
+
+ nsCOMPtr<nsIWebBrowser> mWebBrowser;
+private:
+ GtkWidget *mEmbed;
+
+ nsCOMPtr<nsIWebBrowserFocus> mWebBrowserFocus;
+ nsCOMPtr<nsIDOMDocument> mTargetDocument;
+ nsCOMPtr<nsIDOMEventTarget> mEventTarget;
+ nsCOMPtr<nsIDOMWindow> mDOMWindow;
+ EphyDOMLinkEventListener *mDOMLinkEventListener;
+ EphyMiscDOMEventsListener *mMiscDOMEventsListener;
+ EphyDOMScrollEventListener *mDOMScrollEventListener;
+ EphyPopupBlockEventListener *mPopupBlockEventListener;
+ EphyModalAlertEventListener *mModalAlertListener;
+ EphyContextMenuListener *mContextMenuListener;
+ PRBool mInitialized;
+#ifdef HAVE_MOZILLA_PSM
+ nsCOMPtr<nsISecureBrowserUI> mSecurityInfo;
+#endif
+
+ nsresult GetListener (void);
+ nsresult AttachListeners (void);
+ nsresult DetachListeners (void);
+ nsresult GetSHistory (nsISHistory **aSHistory);
+ nsresult GetContentViewer (nsIContentViewer **aViewer);
+ nsresult GetDocumentHasModifiedForms (nsIDOMDocument *aDomDoc, PRUint32 *aNumTextFields, PRBool *aHasTextArea);
+ PRBool CompareFormsText (nsAString &aDefaultText, nsAString &aUserText);
+};
+
+#endif /* !EPHY_BROWSER_H */
diff --git a/embed/xulrunner/embed/EphyContentPolicy.cpp b/embed/xulrunner/embed/EphyContentPolicy.cpp
new file mode 100644
index 000000000..fc367c2b1
--- /dev/null
+++ b/embed/xulrunner/embed/EphyContentPolicy.cpp
@@ -0,0 +1,244 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright © 2003 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <nsStringAPI.h>
+
+#include <nsCOMPtr.h>
+#include <nsICategoryManager.h>
+#include <nsIDOMAbstractView.h>
+#include <nsIDOMDocument.h>
+#include <nsIDOMDocumentView.h>
+#include <nsIDOMNode.h>
+#include <nsIDOMWindow.h>
+#include <nsIURI.h>
+#include <nsServiceManagerUtils.h>
+#include <nsXPCOMCID.h>
+
+#include "eel-gconf-extensions.h"
+#include "ephy-adblock-manager.h"
+#include "ephy-debug.h"
+#include "ephy-embed-shell.h"
+#include "ephy-embed-single.h"
+
+#include "EphyUtils.h"
+
+#include "EphyContentPolicy.h"
+
+#define CONF_LOCKDOWN_DISABLE_UNSAFE_PROTOCOLS "/apps/epiphany/lockdown/disable_unsafe_protocols"
+#define CONF_LOCKDOWN_ADDITIONAL_SAFE_PROTOCOLS "/apps/epiphany/lockdown/additional_safe_protocols"
+
+NS_IMPL_ISUPPORTS1(EphyContentPolicy, nsIContentPolicy)
+
+EphyContentPolicy::EphyContentPolicy()
+{
+ LOG ("EphyContentPolicy ctor (%p)", this);
+
+ mLocked = eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_UNSAFE_PROTOCOLS);
+
+ mSafeProtocols = eel_gconf_get_string_list (CONF_LOCKDOWN_ADDITIONAL_SAFE_PROTOCOLS);
+}
+
+EphyContentPolicy::~EphyContentPolicy()
+{
+ LOG ("EphyContentPolicy dtor (%p)", this);
+
+ g_slist_foreach (mSafeProtocols, (GFunc) g_free, NULL);
+ g_slist_free (mSafeProtocols);
+}
+
+GtkWidget *
+EphyContentPolicy::GetEmbedFromContext (nsISupports *aContext)
+{
+ /*
+ * aContext is either an nsIDOMWindow, an nsIDOMNode, or NULL. If it's
+ * an nsIDOMNode, we need the nsIDOMWindow to get the EphyEmbed.
+ */
+ if (aContext == NULL) return NULL;
+
+ nsCOMPtr<nsIDOMWindow> window;
+
+ nsCOMPtr<nsIDOMNode> node (do_QueryInterface (aContext));
+ if (node != NULL)
+ {
+ nsCOMPtr<nsIDOMDocument> domDocument;
+
+ node->GetOwnerDocument (getter_AddRefs (domDocument));
+ if (domDocument == NULL) return NULL; /* resource://... */
+
+ nsCOMPtr<nsIDOMDocumentView> docView =
+ do_QueryInterface (domDocument);
+ NS_ENSURE_TRUE (docView, NULL);
+
+ nsCOMPtr<nsIDOMAbstractView> view;
+
+ docView->GetDefaultView (getter_AddRefs (view));
+
+ window = do_QueryInterface (view);
+ }
+ else
+ {
+ window = do_QueryInterface (aContext);
+ }
+ NS_ENSURE_TRUE (window, NULL);
+
+ GtkWidget *embed = EphyUtils::FindEmbed (window);
+ if (!EPHY_IS_EMBED (embed)) return NULL;
+
+ return embed;
+}
+
+NS_IMETHODIMP
+EphyContentPolicy::ShouldLoad(PRUint32 aContentType,
+ nsIURI *aContentLocation,
+ nsIURI *aRequestingLocation,
+ nsISupports *aContext,
+ const nsACString &aMimeTypeGuess,
+ nsISupports *aExtra,
+ PRInt16 *aDecision)
+{
+ NS_ENSURE_ARG (aContentLocation);
+ NS_ENSURE_ARG_POINTER (aDecision);
+
+ *aDecision = nsIContentPolicy::ACCEPT;
+
+ /* We have to always allow these, else forms and scrollbars break */
+ PRBool isChrome = PR_FALSE, isResource = PR_FALSE;
+ aContentLocation->SchemeIs ("chrome", &isChrome);
+ aContentLocation->SchemeIs ("resource", &isResource);
+ if (isChrome || isResource) return NS_OK;
+
+ PRBool isHttps = PR_FALSE;
+ aContentLocation->SchemeIs ("https", &isHttps);
+ if (isHttps) return NS_OK;
+
+ /* is this url allowed ? */
+ nsCString contentSpec;
+ aContentLocation->GetSpec (contentSpec);
+
+ EphyAdBlockManager *adblock_manager =
+ EPHY_ADBLOCK_MANAGER (ephy_embed_shell_get_adblock_manager (embed_shell));
+
+ static PRBool kBlockType[nsIContentPolicy::TYPE_REFRESH + 1] = {
+ PR_FALSE /* unused/unknown, don't block */,
+ PR_TRUE /* TYPE_OTHER */,
+ PR_TRUE /* TYPE_SCRIPT */,
+ PR_TRUE /* TYPE_IMAGE */,
+ PR_FALSE /* TYPE_STYLESHEET */,
+ PR_TRUE /* TYPE_OBJECT */,
+ PR_FALSE /* TYPE_DOCUMENT */,
+ PR_TRUE /* TYPE_SUBDOCUMENT */,
+ PR_TRUE /* TYPE_REFRESH */
+ };
+
+ if (kBlockType[aContentType < G_N_ELEMENTS (kBlockType) ? aContentType : 0])
+ {
+ GtkWidget *embed = GetEmbedFromContext (aContext);
+
+ if (embed &&
+ !ephy_adblock_manager_should_load (adblock_manager,
+ EPHY_EMBED (embed),
+ contentSpec.get (),
+ AdUriCheckType (aContentType)))
+ {
+ *aDecision = nsIContentPolicy::REJECT_REQUEST;
+
+ g_signal_emit_by_name (embed,
+ "content-blocked",
+ contentSpec.get ());
+ return NS_OK;
+ }
+ }
+
+ PRBool isHttp = PR_FALSE;
+ aContentLocation->SchemeIs ("http", &isHttp);
+ if (isHttp) return NS_OK;
+
+ if (strcmp (contentSpec.get(), "about:blank") == 0) return NS_OK;
+
+ nsCString contentScheme;
+ aContentLocation->GetScheme (contentScheme);
+
+ /* first general lockdown check */
+ if (mLocked &&
+ !g_slist_find_custom (mSafeProtocols, contentScheme.get(), (GCompareFunc) strcmp))
+ {
+ *aDecision = nsIContentPolicy::REJECT_REQUEST;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EphyContentPolicy::ShouldProcess(PRUint32 aContentType,
+ nsIURI *aContentLocation,
+ nsIURI *aRequestingLocation,
+ nsISupports *aContext,
+ const nsACString &aMimeType,
+ nsISupports *aExtra,
+ PRInt16 *aDecision)
+{
+ *aDecision = nsIContentPolicy::ACCEPT;
+ return NS_OK;
+}
+
+
+/* static */ NS_METHOD
+EphyContentPolicy::Register (nsIComponentManager* aComponentManager,
+ nsIFile* aPath,
+ const char* aRegistryLocation,
+ const char* aComponentType,
+ const nsModuleComponentInfo* aInfo)
+{
+ nsresult rv;
+ nsCOMPtr<nsICategoryManager> catMan (do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = catMan->AddCategoryEntry ("content-policy",
+ EPHY_CONTENT_POLICY_CONTRACTID,
+ EPHY_CONTENT_POLICY_CONTRACTID,
+ PR_FALSE /* don't persist */,
+ PR_TRUE /* replace */,
+ nsnull);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ return rv;
+}
+
+/* static */ NS_METHOD
+EphyContentPolicy::Unregister (nsIComponentManager* aComponentManager,
+ nsIFile* aPath,
+ const char* aRegistryLocation,
+ const nsModuleComponentInfo* aInfo)
+{
+ nsresult rv;
+ nsCOMPtr<nsICategoryManager> catMan (do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = catMan->DeleteCategoryEntry ("content-policy",
+ EPHY_CONTENT_POLICY_CONTRACTID,
+ PR_FALSE /* don't persist */);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ return rv;
+}
diff --git a/embed/xulrunner/embed/EphyContentPolicy.h b/embed/xulrunner/embed/EphyContentPolicy.h
new file mode 100644
index 000000000..0bc68ced7
--- /dev/null
+++ b/embed/xulrunner/embed/EphyContentPolicy.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright © 2003 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_CONTENT_POLICY_H
+#define EPHY_CONTENT_POLICY_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtkwidget.h>
+
+#include <nsIContentPolicy.h>
+
+#include "ephy-embed.h"
+
+class nsIComponentManager;
+class nsIFile;
+struct nsModuleComponentInfo;
+
+#define EPHY_CONTENT_POLICY_CONTRACTID "@gnome.org/projects/epiphany/epiphany-content-policy;1"
+#define EPHY_CONTENT_POLICY_CLASSNAME "Epiphany Content Policy Class"
+
+#define EPHY_CONTENT_POLICY_CID \
+{ /* 6bb60b15-b7bd-4023-a19e-ab691bc3fb43 */ \
+ 0x6bb60b15, \
+ 0xb7bd, \
+ 0x4023, \
+ { 0xa1, 0x9e, 0xab, 0x69, 0x1b, 0xc3, 0xfb, 0x43 } \
+}
+
+class EphyContentPolicy : public nsIContentPolicy
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICONTENTPOLICY
+
+ EphyContentPolicy();
+
+ static NS_METHOD Register (nsIComponentManager* aComponentManager,
+ nsIFile* aPath,
+ const char* aRegistryLocation,
+ const char* aComponentType,
+ const nsModuleComponentInfo* aInfo);
+
+ static NS_METHOD Unregister (nsIComponentManager* aComponentManager,
+ nsIFile* aPath,
+ const char* aRegistryLocation,
+ const nsModuleComponentInfo* aInfo);
+
+ private:
+ ~EphyContentPolicy();
+
+ static GtkWidget *GetEmbedFromContext (nsISupports *aContext);
+
+ gboolean mLocked;
+ GSList *mSafeProtocols;
+};
+
+#endif
diff --git a/embed/xulrunner/embed/EphyDirectoryProvider.cpp b/embed/xulrunner/embed/EphyDirectoryProvider.cpp
new file mode 100644
index 000000000..f8ec21042
--- /dev/null
+++ b/embed/xulrunner/embed/EphyDirectoryProvider.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <string.h>
+
+#ifndef HAVE_GECKO_1_9
+// for nsNetUtil.h
+#define MOZILLA_INTERNAL_API 1
+#endif
+
+#include <nsStringAPI.h>
+
+#include <nsAppDirectoryServiceDefs.h>
+#include <nsCOMPtr.h>
+#include <nsEnumeratorUtils.h>
+#include <nsIDirectoryService.h>
+#include <nsIIOService.h>
+#include <nsILocalFile.h>
+#include <nsISupportsArray.h>
+#include <nsIToolkitChromeRegistry.h>
+#include <nsNetUtil.h>
+
+#include "EphyDirectoryProvider.h"
+
+NS_IMPL_ISUPPORTS2 (EphyDirectoryProvider,
+ nsIDirectoryServiceProvider,
+ nsIDirectoryServiceProvider2)
+
+
+/* nsIFile getFile (in string prop, out PRBool persistent); */
+NS_IMETHODIMP
+EphyDirectoryProvider::GetFile (const char *prop,
+ PRBool *persistent,
+ nsIFile **_retval)
+{
+ return NS_ERROR_FAILURE;
+}
+
+/* nsISimpleEnumerator getFiles (in string prop); */
+NS_IMETHODIMP
+EphyDirectoryProvider::GetFiles (const char *prop,
+ nsISimpleEnumerator **_retval)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (prop && strcmp (prop, NS_CHROME_MANIFESTS_FILE_LIST) == 0)
+ {
+ nsCOMPtr<nsILocalFile> manifestDir;
+ rv = NS_NewNativeLocalFile (nsDependentCString(SHARE_DIR "/chrome"), PR_TRUE,
+ getter_AddRefs (manifestDir));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsISupports> element (do_QueryInterface (manifestDir, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ /* FIXME: this sucks!
+ * When we don't implement a directory service provider,
+ * the chrome registry takes its manifests files from the
+ * app chrome dir; but it doesn't append this dir when
+ * we do provide our own (additional) chrome manifest dirs!
+ * http://lxr.mozilla.org/seamonkey/source/chrome/src/nsChromeRegistry.cpp#1147
+ */
+ nsCOMPtr<nsIProperties> dirServ (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIFile> chromeDir;
+ rv = dirServ->Get (NS_APP_CHROME_DIR, NS_GET_IID (nsIFile),
+ getter_AddRefs (chromeDir));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsISupportsArray> array;
+ rv = NS_NewISupportsArray (getter_AddRefs (array));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = array->AppendElement (manifestDir);
+ rv |= array->AppendElement (chromeDir);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = NS_NewArrayEnumerator (_retval, array);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = NS_SUCCESS_AGGREGATE_RESULT;
+ }
+
+ return rv;
+}
diff --git a/embed/xulrunner/embed/EphyDirectoryProvider.h b/embed/xulrunner/embed/EphyDirectoryProvider.h
new file mode 100644
index 000000000..ca66f9d4d
--- /dev/null
+++ b/embed/xulrunner/embed/EphyDirectoryProvider.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_DIRECTORY_PROVIDER_H
+#define EPHY_DIRECTORY_PROVIDER_H
+
+#include <nsIDirectoryService.h>
+
+class EphyDirectoryProvider : public nsIDirectoryServiceProvider2
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
+
+ EphyDirectoryProvider() { }
+ virtual ~EphyDirectoryProvider() { }
+};
+
+#endif /* EPHY_DIRECTORY_PROVIDER_H */
diff --git a/embed/xulrunner/embed/EphyFind.cpp b/embed/xulrunner/embed/EphyFind.cpp
new file mode 100644
index 000000000..344d4251e
--- /dev/null
+++ b/embed/xulrunner/embed/EphyFind.cpp
@@ -0,0 +1,267 @@
+/*
+ * Copyright © 2005 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib.h>
+
+#include <nsStringAPI.h>
+
+#include <nsComponentManagerUtils.h>
+#include <nsCOMPtr.h>
+#include <nsIDocShell.h>
+#include <nsIDOMAbstractView.h>
+#include <nsIDOMDocumentEvent.h>
+#include <nsIDOMDocument.h>
+#include <nsIDOMDocumentView.h>
+#include <nsIDOMElement.h>
+#include <nsIDOMEvent.h>
+#include <nsIDOMEventTarget.h>
+#include <nsIDOMHTMLAnchorElement.h>
+#include <nsIDOMKeyEvent.h>
+#include <nsIDOMNode.h>
+#include <nsIDOMWindow.h>
+#include <nsIInterfaceRequestorUtils.h>
+#include <nsISelectionController.h>
+#include <nsISelectionDisplay.h>
+#include <nsITypeAheadFind.h>
+#include <nsIWebBrowserFocus.h>
+#include <nsIWebBrowser.h>
+#include <nsServiceManagerUtils.h>
+
+#ifndef HAVE_GECKO_1_9
+#include <nsIDocShellTreeItem.h>
+#include <nsISimpleEnumerator.h>
+#endif
+
+#include "gecko-embed-private.h"
+
+#include "ephy-debug.h"
+
+#include "EphyFind.h"
+
+#define NS_TYPEAHEADFIND_CONTRACTID "@mozilla.org/typeaheadfind;1"
+
+static const PRUnichar kKeyEvents[] = { 'K', 'e', 'y', 'E', 'v', 'e', 'n', 't', 's', '\0' };
+static const PRUnichar kKeyPress[] = { 'k', 'e', 'y', 'p', 'r', 'e', 's', 's', '\0' };
+
+EphyFind::EphyFind ()
+: mCurrentEmbed(nsnull)
+, mAttention(PR_FALSE)
+{
+ LOG ("EphyFind ctor [%p]", this);
+}
+
+EphyFind::~EphyFind ()
+{
+ LOG ("EphyFind dtor [%p]", this);
+}
+
+nsresult
+EphyFind::SetEmbed (EphyEmbed *aEmbed)
+{
+ nsresult rv = NS_OK;
+ if (aEmbed == mCurrentEmbed) return rv;
+
+ SetSelectionAttention (PR_FALSE);
+
+ mCurrentEmbed = nsnull;
+ mWebBrowser = nsnull;
+
+ rv = NS_ERROR_FAILURE;
+ gecko_embed_get_nsIWebBrowser (GECKO_EMBED (aEmbed),
+ getter_AddRefs (mWebBrowser));
+ NS_ENSURE_TRUE (mWebBrowser, rv);
+
+ nsCOMPtr<nsIDocShell> docShell (do_GetInterface (mWebBrowser, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ if (!mFinder) {
+ mFinder = do_CreateInstance (NS_TYPEAHEADFIND_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = mFinder->Init (docShell);
+#ifdef HAVE_GECKO_1_9
+// mFinder->SetSelectionModeAndRepaint (nsISelectionController::SELECTION_ON);
+#else
+ mFinder->SetFocusLinks (PR_TRUE);
+#endif
+ } else {
+ rv = mFinder->SetDocShell (docShell);
+ }
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ mCurrentEmbed = aEmbed;
+
+ return rv;
+}
+
+void
+EphyFind::SetFindProperties (const char *aSearchString,
+ PRBool aCaseSensitive)
+{
+ if (!mFinder) return;
+
+ mFinder->SetCaseSensitive (aCaseSensitive);
+ /* search string is set on ::Find */
+}
+
+void
+EphyFind::SetSelectionAttention (PRBool aAttention)
+{
+ if (aAttention == mAttention) return;
+
+ mAttention = aAttention;
+
+ PRInt16 display;
+ if (aAttention) {
+ display = nsISelectionController::SELECTION_ATTENTION;
+ } else {
+ display = nsISelectionController::SELECTION_ON;
+ }
+
+#ifdef HAVE_GECKO_1_9
+ if (mFinder) {
+ mFinder->SetSelectionModeAndRepaint (display);
+ }
+#else
+ nsresult rv;
+ nsCOMPtr<nsIDocShell> shell (do_GetInterface (mWebBrowser, &rv));
+ /* It's okay for this to fail, if the tab is closing, or if
+ * we weren't attached to any tab yet
+ */
+ if (NS_FAILED (rv) || !shell) return;
+
+ nsCOMPtr<nsISimpleEnumerator> enumerator;
+ rv = shell->GetDocShellEnumerator (nsIDocShellTreeItem::typeContent,
+ nsIDocShell::ENUMERATE_FORWARDS,
+ getter_AddRefs (enumerator));
+ NS_ENSURE_SUCCESS (rv, );
+
+ PRBool hasMore = PR_FALSE;
+ while (NS_SUCCEEDED (enumerator->HasMoreElements (&hasMore)) && hasMore) {
+ nsCOMPtr<nsISupports> element;
+ enumerator->GetNext (getter_AddRefs (element));
+ if (!element) continue;
+
+ nsCOMPtr<nsISelectionDisplay> sd (do_GetInterface (element));
+ if (!sd) continue;
+
+ nsCOMPtr<nsISelectionController> controller (do_QueryInterface (sd));
+ if (!controller) continue;
+
+ controller->SetDisplaySelection (display);
+ }
+#endif /* HAVE_GECKO_1_9 */
+}
+
+EphyEmbedFindResult
+EphyFind::Find (const char *aSearchString,
+ PRBool aLinksOnly)
+{
+ if (!mFinder) return EPHY_EMBED_FIND_NOTFOUND;
+
+ nsString uSearchString;
+ NS_CStringToUTF16 (nsCString (aSearchString ? aSearchString : ""),
+ NS_CSTRING_ENCODING_UTF8, uSearchString);
+
+ SetSelectionAttention (PR_TRUE);
+
+ nsresult rv;
+ PRUint16 found = nsITypeAheadFind::FIND_NOTFOUND;
+ rv = mFinder->Find (uSearchString, aLinksOnly, &found);
+
+ return (EphyEmbedFindResult) found;
+}
+
+EphyEmbedFindResult
+EphyFind::FindAgain (PRBool aForward,
+ PRBool aLinksOnly)
+{
+ if (!mFinder) return EPHY_EMBED_FIND_NOTFOUND;
+
+ SetSelectionAttention (PR_TRUE);
+
+ nsresult rv;
+ PRUint16 found = nsITypeAheadFind::FIND_NOTFOUND;
+#ifdef HAVE_GECKO_1_9
+ rv = mFinder->FindAgain (!aForward, aLinksOnly, &found);
+#else
+ if (aForward) {
+ rv = mFinder->FindNext (&found);
+ } else {
+ rv = mFinder->FindPrevious (&found);
+ }
+#endif
+
+ return (EphyEmbedFindResult) found;
+}
+
+PRBool
+EphyFind::ActivateLink (GdkModifierType aMask)
+{
+ nsresult rv;
+ nsCOMPtr<nsIDOMElement> link;
+ rv = mFinder->GetFoundLink (getter_AddRefs (link));
+ if (NS_FAILED (rv) || !link) return FALSE;
+
+ nsCOMPtr<nsIDOMDocument> doc;
+ rv = link->GetOwnerDocument (getter_AddRefs (doc));
+ NS_ENSURE_TRUE (doc, FALSE);
+
+ nsCOMPtr<nsIDOMDocumentView> docView (do_QueryInterface (doc));
+ NS_ENSURE_TRUE (docView, FALSE);
+
+ nsCOMPtr<nsIDOMAbstractView> abstractView;
+ docView->GetDefaultView (getter_AddRefs (abstractView));
+ NS_ENSURE_TRUE (abstractView, FALSE);
+
+ nsCOMPtr<nsIDOMDocumentEvent> docEvent (do_QueryInterface (doc));
+ NS_ENSURE_TRUE (docEvent, FALSE);
+
+ nsCOMPtr<nsIDOMEvent> event;
+ rv = docEvent->CreateEvent (nsString(kKeyEvents), getter_AddRefs (event));
+ NS_ENSURE_SUCCESS (rv, FALSE);
+
+ nsCOMPtr<nsIDOMKeyEvent> keyEvent (do_QueryInterface (event));
+ NS_ENSURE_TRUE (keyEvent, FALSE);
+
+ rv = keyEvent->InitKeyEvent (nsString (kKeyPress),
+ PR_TRUE /* bubble */,
+ PR_TRUE /* cancelable */,
+ abstractView,
+ (aMask & GDK_CONTROL_MASK) != 0,
+ (aMask & GDK_MOD1_MASK) != 0 /* Alt */,
+ (aMask & GDK_SHIFT_MASK) != 0,
+ /* FIXME when we upgrade to gtk 2.10 */
+ PR_FALSE /* Meta */,
+ nsIDOMKeyEvent::DOM_VK_RETURN,
+ 0);
+ NS_ENSURE_SUCCESS (rv, FALSE);
+
+ nsCOMPtr<nsIDOMEventTarget> target (do_QueryInterface (link));
+ NS_ENSURE_TRUE (target, FALSE);
+
+ PRBool defaultPrevented = PR_FALSE;
+ rv = target->DispatchEvent (event, &defaultPrevented);
+
+ return NS_SUCCEEDED (rv) && defaultPrevented;
+}
diff --git a/embed/xulrunner/embed/EphyFind.h b/embed/xulrunner/embed/EphyFind.h
new file mode 100644
index 000000000..34c30517d
--- /dev/null
+++ b/embed/xulrunner/embed/EphyFind.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2005 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef TYPEAHEADFIND_H
+#define TYPEAHEADFIND_H
+
+#include <gdk/gdktypes.h>
+
+class nsITypeAheadFind;
+class nsIWebBrowser;
+class nsIWebBrowserFind;
+
+#include <nsCOMPtr.h>
+
+#include "ephy-embed.h"
+#include "ephy-embed-find.h"
+
+class EphyFind
+{
+ public:
+ EphyFind ();
+ ~EphyFind ();
+
+ nsresult SetEmbed (EphyEmbed *aEmbed);
+ void SetFindProperties (const char *aSearchString,
+ PRBool aCaseSensitive);
+ void SetSelectionAttention (PRBool aAttention);
+ EphyEmbedFindResult Find (const char *aSearchString,
+ PRBool aLinksOnly);
+ EphyEmbedFindResult FindAgain (PRBool aForward,
+ PRBool aLinksOnly);
+ PRBool ActivateLink (GdkModifierType aMask);
+
+ private:
+ EphyEmbed *mCurrentEmbed;
+
+ nsCOMPtr<nsIWebBrowser> mWebBrowser;
+
+ nsCOMPtr<nsITypeAheadFind> mFinder;
+ PRPackedBool mAttention;
+};
+
+#endif /* !TYPEAHEADFIND_H */
diff --git a/embed/xulrunner/embed/EphyHeaderSniffer.cpp b/embed/xulrunner/embed/EphyHeaderSniffer.cpp
new file mode 100644
index 000000000..6ef9318de
--- /dev/null
+++ b/embed/xulrunner/embed/EphyHeaderSniffer.cpp
@@ -0,0 +1,442 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Chimera code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright © 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * David Hyatt <hyatt@netscape.com>
+ * Simon Fraser <sfraser@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+
+#include <nsStringAPI.h>
+
+#include <nsComponentManagerUtils.h>
+#include <nsIChannel.h>
+#include <nsIDOMDocument.h>
+#include <nsIDOMHTMLDocument.h>
+#include <nsIDownload.h>
+#include <nsIHttpChannel.h>
+#include <nsIInputStream.h>
+#include <nsILocalFile.h>
+#include <nsIMIMEHeaderParam.h>
+#include <nsIMIMEInfo.h>
+#include <nsIMIMEService.h>
+#include <nsIPrefService.h>
+#include <nsIPromptService.h>
+#include <nsIURI.h>
+#include <nsIURL.h>
+#include <nsIWebBrowserPersist.h>
+#include <nsIWindowWatcher.h>
+#include <nsServiceManagerUtils.h>
+#include <nsXPCOMCID.h>
+
+#include "eel-gconf-extensions.h"
+#include "ephy-debug.h"
+#include "ephy-file-chooser.h"
+#include "ephy-gui.h"
+#include "ephy-prefs.h"
+
+#include "EphyBadCertRejector.h"
+#include "MozDownload.h"
+
+#include "EphyHeaderSniffer.h"
+
+EphyHeaderSniffer::EphyHeaderSniffer (nsIWebBrowserPersist* aPersist, MozillaEmbedPersist *aEmbedPersist,
+ nsIFile* aFile, nsIURI* aURL, nsIDOMDocument* aDocument, nsIInputStream* aPostData,
+ EphyEmbedSingle *single)
+: mPersist(aPersist)
+, mEmbedPersist(aEmbedPersist)
+, mTmpFile(aFile)
+, mURL(aURL)
+, mOriginalURI(nsnull)
+, mDocument(aDocument)
+, mPostData(aPostData)
+{
+ LOG ("EphyHeaderSniffer ctor (%p)", this);
+
+ nsCOMPtr<nsIWindowWatcher> watcher
+ (do_GetService("@mozilla.org/embedcomp/window-watcher;1"));
+ if (!watcher) return;
+
+ watcher->GetNewAuthPrompter (nsnull, getter_AddRefs (mAuthPrompt));
+
+ mSingle = single;
+ g_object_add_weak_pointer (G_OBJECT (mSingle),
+ (gpointer *)&mSingle);
+}
+
+EphyHeaderSniffer::~EphyHeaderSniffer()
+{
+ LOG ("EphyHeaderSniffer dtor (%p)", this);
+
+ if (mSingle)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (mSingle),
+ (gpointer *)&mSingle);
+ }
+}
+
+NS_IMPL_ISUPPORTS3 (EphyHeaderSniffer,
+ nsIWebProgressListener,
+ nsIInterfaceRequestor,
+ nsIAuthPrompt)
+
+NS_IMETHODIMP
+EphyHeaderSniffer::HandleContent ()
+{
+ gboolean handled = FALSE;
+ nsCString uriSpec;
+
+ if (mPostData || !mSingle) return NS_ERROR_FAILURE;
+
+ mURL->GetSpec (uriSpec);
+
+ g_signal_emit_by_name (mSingle, "handle_content", mContentType.get(),
+ uriSpec.get(), &handled);
+
+ return handled ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+EphyHeaderSniffer::OnStateChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags,
+ PRUint32 aStatus)
+{
+ if (aStateFlags & nsIWebProgressListener::STATE_START)
+ {
+ /* be sure to keep it alive while we save since it owns
+ us as a listener and keep ourselves alive */
+ nsCOMPtr<nsIWebBrowserPersist> kungFuDeathGrip(mPersist);
+ nsCOMPtr<nsIWebProgressListener> kungFuSuicideGrip(this);
+
+ nsresult rv;
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest, &rv);
+ if (!channel) return rv;
+ channel->GetContentType(mContentType);
+
+ nsCOMPtr<nsIURI> origURI;
+ channel->GetOriginalURI(getter_AddRefs(origURI));
+
+ nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
+ if (httpChannel)
+ {
+ httpChannel->GetResponseHeader(nsCString("content-disposition"),
+ mContentDisposition);
+ }
+
+ mPersist->CancelSave();
+
+ PRBool exists;
+ mTmpFile->Exists(&exists);
+ if (exists)
+ {
+ mTmpFile->Remove(PR_FALSE);
+ }
+
+ rv = HandleContent ();
+ if (NS_SUCCEEDED (rv)) return NS_OK;
+
+ rv = PerformSave(origURI);
+ if (NS_FAILED(rv))
+ {
+ /* FIXME put up some UI */
+
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EphyHeaderSniffer::OnProgressChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRInt32 aCurSelfProgress,
+ PRInt32 aMaxSelfProgress,
+ PRInt32 aCurTotalProgress,
+ PRInt32 aMaxTotalProgress)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EphyHeaderSniffer::OnLocationChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ nsIURI *location)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EphyHeaderSniffer::OnStatusChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ nsresult aStatus,
+ const PRUnichar *aMessage)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EphyHeaderSniffer::OnSecurityChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state)
+{
+ return NS_OK;
+}
+
+/* void getInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
+NS_IMETHODIMP
+EphyHeaderSniffer::GetInterface(const nsIID & uuid, void * *result)
+{
+ if (uuid.Equals (NS_GET_IID (nsIBadCertListener)) &&
+ mEmbedPersist)
+ {
+ EphyEmbedPersistFlags flags;
+
+ g_object_get (mEmbedPersist, "flags", &flags, (char *) NULL);
+
+ if (flags & EPHY_EMBED_PERSIST_NO_CERTDIALOGS)
+ {
+ EphyBadCertRejector *badCertRejector = new EphyBadCertRejector ();
+ if (!badCertRejector) return NS_ERROR_OUT_OF_MEMORY;
+
+ *result = static_cast<nsIBadCertListener*>(badCertRejector);
+ NS_ADDREF (badCertRejector);
+
+ return NS_OK;
+ }
+ }
+
+ return NS_ERROR_NO_INTERFACE;
+}
+
+static void
+filechooser_response_cb (GtkWidget *dialog,
+ gint response,
+ EphyHeaderSniffer* sniffer)
+{
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ char *filename;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+ if (ephy_gui_check_location_writable (dialog, filename) == FALSE)
+ {
+ g_free (filename);
+ return;
+ }
+
+ nsCOMPtr<nsILocalFile> destFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
+ if (destFile)
+ {
+ destFile->InitWithNativePath (nsCString (filename));
+
+ sniffer->InitiateDownload (destFile);
+ }
+
+ g_free (filename);
+ }
+
+ // FIXME how to inform user of failed save ?
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+nsresult EphyHeaderSniffer::PerformSave (nsIURI* inOriginalURI)
+{
+ nsresult rv;
+ EphyEmbedPersistFlags flags;
+ PRBool askDownloadDest;
+
+ mOriginalURI = inOriginalURI;
+
+ flags = ephy_embed_persist_get_flags (EPHY_EMBED_PERSIST (mEmbedPersist));
+ askDownloadDest = flags & EPHY_EMBED_PERSIST_ASK_DESTINATION;
+
+ nsString defaultFileName;
+
+ if (!defaultFileName.Length() && mContentDisposition.Length())
+ {
+ /* 1 Use the HTTP header suggestion. */
+ nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
+ do_GetService("@mozilla.org/network/mime-hdrparam;1");
+
+ if (mimehdrpar)
+ {
+ nsCString fallbackCharset;
+ if (mURL)
+ {
+ mURL->GetOriginCharset(fallbackCharset);
+ }
+
+ nsString fileName;
+
+ rv = mimehdrpar->GetParameter (mContentDisposition, "filename",
+ fallbackCharset, PR_TRUE, nsnull,
+ fileName);
+ if (NS_FAILED(rv) || !fileName.Length())
+ {
+ rv = mimehdrpar->GetParameter (mContentDisposition, "name",
+ fallbackCharset, PR_TRUE, nsnull,
+ fileName);
+ }
+
+ if (NS_SUCCEEDED(rv) && fileName.Length())
+ {
+ defaultFileName = fileName;
+ }
+ }
+ }
+
+ if (!defaultFileName.Length())
+ {
+ /* 2 For file URLs, use the file name. */
+
+ nsCOMPtr<nsIURL> url(do_QueryInterface(mURL));
+ if (url)
+ {
+ nsCString fileNameCString;
+ url->GetFileName(fileNameCString);
+ NS_CStringToUTF16 (fileNameCString, NS_CSTRING_ENCODING_UTF8,
+ defaultFileName);
+ }
+ }
+
+ if (!defaultFileName.Length() && mDocument)
+ {
+ /* 3 Use the title of the document. */
+
+ nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(mDocument));
+ if (htmlDoc)
+ {
+ htmlDoc->GetTitle(defaultFileName);
+ }
+ }
+
+ if (!defaultFileName.Length() && mURL)
+ {
+ /* 4 Use the host. */
+ nsCString hostName;
+ mURL->GetHost(hostName);
+ NS_CStringToUTF16 (hostName, NS_CSTRING_ENCODING_UTF8,
+ defaultFileName);
+ }
+
+ /* 5 One last case to handle about:blank and other untitled pages. */
+ if (!defaultFileName.Length())
+ {
+ NS_CStringToUTF16 (nsCString(_("Untitled")),
+ NS_CSTRING_ENCODING_UTF8, defaultFileName);
+ }
+
+ /* Validate the file name to ensure legality. */
+ nsCString cDefaultFileName;
+ NS_UTF16ToCString (defaultFileName, NS_CSTRING_ENCODING_UTF8,
+ cDefaultFileName);
+ char *default_name = g_strdup (cDefaultFileName.get());
+ default_name = g_strdelimit (default_name, "/\\:", ' ');
+
+ const char *key;
+ key = ephy_embed_persist_get_persist_key (EPHY_EMBED_PERSIST (mEmbedPersist));
+
+ /* FIXME: do better here by using nsITextToSubURI service, like in
+ * http://lxr.mozilla.org/seamonkey/source/xpfe/communicator/resources/content/contentAreaUtils.js#763
+ */
+ char *filename;
+ filename = gnome_vfs_unescape_string (default_name, NULL);
+
+ if (!g_utf8_validate (filename, -1, NULL))
+ {
+ g_free (filename);
+ filename = g_strdup (default_name);
+ }
+
+ g_free (default_name);
+
+ if (askDownloadDest)
+ {
+ EphyFileChooser *dialog;
+ GtkWindow *window;
+ const char *title;
+ guint32 user_time;
+
+ title = ephy_embed_persist_get_fc_title (EPHY_EMBED_PERSIST (mEmbedPersist));
+ window = ephy_embed_persist_get_fc_parent (EPHY_EMBED_PERSIST (mEmbedPersist));
+
+ user_time = ephy_embed_persist_get_user_time (EPHY_EMBED_PERSIST (mEmbedPersist));
+ if (user_time == 0)
+ {
+ g_warning ("EphyHeaderSniffer::PerformSave without valid user time!\n");
+ }
+
+ dialog = ephy_file_chooser_new (title ? title: _("Save"),
+ GTK_WIDGET (window),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ key ? key : CONF_STATE_SAVE_DIR,
+ EPHY_FILE_FILTER_ALL_SUPPORTED);
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog),
+ filename);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (filechooser_response_cb), this);
+
+ ephy_gui_window_update_user_time (GTK_WIDGET (dialog), user_time);
+ gtk_widget_show (GTK_WIDGET (dialog));
+
+ g_free (filename);
+ return NS_OK;
+ }
+ /* FIXME: how to inform user of failed save ? */
+
+ nsCOMPtr<nsILocalFile> destFile;
+ BuildDownloadPath (filename, getter_AddRefs (destFile));
+ g_free (filename);
+ NS_ENSURE_TRUE (destFile, NS_ERROR_FAILURE);
+
+ return InitiateDownload (destFile);
+}
+
+nsresult EphyHeaderSniffer::InitiateDownload (nsILocalFile *aDestFile)
+{
+ LOG ("Initiating download");
+
+ return InitiateMozillaDownload (mDocument, mURL, aDestFile,
+ mContentType.get(), mOriginalURI, mEmbedPersist,
+ mPostData, nsnull, -1);
+}
diff --git a/embed/xulrunner/embed/EphyHeaderSniffer.h b/embed/xulrunner/embed/EphyHeaderSniffer.h
new file mode 100644
index 000000000..ec73c3164
--- /dev/null
+++ b/embed/xulrunner/embed/EphyHeaderSniffer.h
@@ -0,0 +1,95 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Chimera code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright © 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * David Hyatt <hyatt@netscape.com>
+ * Simon Fraser <sfraser@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_HEADER_SNIFFER_H
+#define EPHY_HEADER_SNIFFER_H
+
+class nsIDOMDocument;
+class nsIFile;
+class nsIInputStream;
+class nsILocalFile;
+class nsIURI;
+class nsIWebBrowserPersist;
+
+#include <nsCOMPtr.h>
+#include <nsIAuthPrompt.h>
+#include <nsIInterfaceRequestor.h>
+#include <nsIWebProgressListener.h>
+
+#include "mozilla-embed-persist.h"
+#include "ephy-embed-single.h"
+
+class EphyHeaderSniffer : public nsIWebProgressListener,
+ public nsIInterfaceRequestor,
+ public nsIAuthPrompt
+{
+public:
+ EphyHeaderSniffer (nsIWebBrowserPersist* aPersist, MozillaEmbedPersist *aEmbedPersist,
+ nsIFile* aFile, nsIURI* aURL, nsIDOMDocument* aDocument,
+ nsIInputStream* aPostData, EphyEmbedSingle *single);
+ virtual ~EphyHeaderSniffer ();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIWEBPROGRESSLISTENER
+ NS_FORWARD_SAFE_NSIAUTHPROMPT(mAuthPrompt)
+ NS_DECL_NSIINTERFACEREQUESTOR
+
+ nsresult InitiateDownload (nsILocalFile *aDestFile);
+
+protected:
+ nsresult PerformSave (nsIURI* inOriginalURI);
+ nsresult HandleContent ();
+
+private:
+ nsIWebBrowserPersist* mPersist; /* Weak. It owns us as a listener. */
+ MozillaEmbedPersist *mEmbedPersist;
+ EphyEmbedSingle *mSingle;
+ nsCOMPtr<nsIFile> mTmpFile;
+ nsCOMPtr<nsIURI> mURL;
+ nsCOMPtr<nsIURI> mOriginalURI;
+ nsCOMPtr<nsIDOMDocument> mDocument;
+ nsCOMPtr<nsIInputStream> mPostData;
+ nsCString mContentType;
+ nsCString mContentDisposition;
+ nsCOMPtr<nsIAuthPrompt> mAuthPrompt;
+};
+
+#endif /* !EPHY_HEADER_SNIFFER_H */
diff --git a/embed/xulrunner/embed/EphyHistoryListener.cpp b/embed/xulrunner/embed/EphyHistoryListener.cpp
new file mode 100644
index 000000000..232c3ccb9
--- /dev/null
+++ b/embed/xulrunner/embed/EphyHistoryListener.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright © 2004 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <nsStringAPI.h>
+
+#include <nsCOMPtr.h>
+#include <nsCURILoader.h>
+#include <nsIChannel.h>
+#include <nsIDocumentLoader.h>
+#include <nsIHttpChannel.h>
+#include <nsIRequest.h>
+#include <nsIRequestObserver.h>
+#include <nsISupportsUtils.h>
+#include <nsIURI.h>
+#include <nsIWebProgress.h>
+#include <nsNetCID.h>
+#include <nsServiceManagerUtils.h>
+
+#include "EphyUtils.h"
+
+#include "ephy-debug.h"
+
+#include "EphyHistoryListener.h"
+
+EphyHistoryListener::EphyHistoryListener ()
+{
+ LOG ("EphyHistoryListener ctor");
+}
+
+EphyHistoryListener::~EphyHistoryListener ()
+{
+ LOG ("EphyHistoryListener dtor");
+}
+
+nsresult
+EphyHistoryListener::Init (EphyHistory *aHistory)
+{
+ mHistory = aHistory;
+
+ nsresult rv;
+ nsCOMPtr<nsIWebProgress> webProgress
+ (do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID, &rv));
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && webProgress, rv);
+
+ rv = webProgress->AddProgressListener
+ (static_cast<nsIWebProgressListener*>(this),
+ nsIWebProgress::NOTIFY_STATE_REQUEST);
+
+ return rv;
+}
+
+NS_IMPL_ISUPPORTS2 (EphyHistoryListener,
+ nsIWebProgressListener,
+ nsISupportsWeakReference)
+
+/* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aStateFlags, in nsresult aStatus); */
+NS_IMETHODIMP
+EphyHistoryListener::OnStateChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRUint32 aStateFlags,
+ nsresult aStatus)
+{
+ nsresult rv = NS_OK;
+
+ /* we only care about redirects */
+ if (! (aStateFlags & nsIWebProgressListener::STATE_REDIRECTING))
+ {
+ return rv;
+ }
+
+ nsCOMPtr<nsIChannel> channel (do_QueryInterface (aRequest));
+ nsCOMPtr<nsIHttpChannel> httpChannel (do_QueryInterface (channel));
+ if (!httpChannel) return rv;
+
+ PRUint32 status = 0;
+ rv = httpChannel->GetResponseStatus (&status);
+ if (rv == NS_ERROR_NOT_AVAILABLE) return NS_OK;
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ /* we're only interested in 301 redirects (moved permanently) */
+ if (status != 301) return NS_OK;
+
+ nsCOMPtr<nsIURI> fromURI;
+ rv = channel->GetURI (getter_AddRefs (fromURI));
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && fromURI, rv);
+
+ nsCString location;
+ rv = httpChannel->GetResponseHeader
+ (nsCString ("Location"), location);
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && location.Length(), rv);
+
+ nsCOMPtr<nsIURI> toURI;
+ rv = EphyUtils::NewURI (getter_AddRefs (toURI), location,
+ nsnull /* use origin charset of fromURI */, fromURI);
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && toURI, rv);
+
+ nsCString fromSpec, toSpec;
+ rv = fromURI->GetSpec (fromSpec);
+ rv |= toURI->GetSpec(toSpec);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ g_signal_emit_by_name (mHistory, "redirect",
+ fromSpec.get(), toSpec.get());
+
+ return rv;
+}
+
+/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
+NS_IMETHODIMP
+EphyHistoryListener::OnProgressChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRInt32 aCurSelfProgress,
+ PRInt32 aMaxSelfProgress,
+ PRInt32 aCurTotalProgress,
+ PRInt32 aMaxTotalProgress)
+{
+ NS_NOTREACHED("notification excluded in AddProgressListener(...)");
+ return NS_OK;
+}
+
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
+NS_IMETHODIMP
+EphyHistoryListener::OnLocationChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ nsIURI *location)
+{
+ NS_NOTREACHED("notification excluded in AddProgressListener(...)");
+ return NS_OK;
+}
+
+/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
+NS_IMETHODIMP
+EphyHistoryListener::OnStatusChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ nsresult aStatus,
+ const PRUnichar *aMessage)
+{
+ NS_NOTREACHED("notification excluded in AddProgressListener(...)");
+ return NS_OK;
+}
+
+/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
+NS_IMETHODIMP
+EphyHistoryListener::OnSecurityChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRUint32 state)
+{
+ NS_NOTREACHED("notification excluded in AddProgressListener(...)");
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/EphyHistoryListener.h b/embed/xulrunner/embed/EphyHistoryListener.h
new file mode 100644
index 000000000..23f955f05
--- /dev/null
+++ b/embed/xulrunner/embed/EphyHistoryListener.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2004 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_REDIRECT_LISTENER_H
+#define EPHY_REDIRECT_LISTENER_H
+
+#include "ephy-history.h"
+
+#include <nsIWebProgressListener.h>
+#include <nsWeakReference.h>
+
+/* 6a9533c6-f068-4e63-8225-5feba0b54d6b */
+#define EPHY_REDIRECTLISTENER_CID \
+{ 0x6a9533c6, 0xf068, 0x4e63, { 0x82, 0x25, 0x5f, 0xeb, 0xa0, 0xb5, 0x4d, 0x6b } }
+#define EPHY_REDIRECTLISTENER_CLASSNAME "Epiphany Redirect Listener Class"
+
+class EphyHistoryListener : public nsIWebProgressListener,
+ public nsSupportsWeakReference
+{
+ public:
+ EphyHistoryListener();
+ virtual ~EphyHistoryListener();
+
+ nsresult Init (EphyHistory *aHistory);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIWEBPROGRESSLISTENER
+ private:
+ EphyHistory *mHistory;
+};
+
+#endif /* EPHY_REDIRECT_LISTENER_H */
diff --git a/embed/xulrunner/embed/EphyPromptService.cpp b/embed/xulrunner/embed/EphyPromptService.cpp
new file mode 100644
index 000000000..29813f300
--- /dev/null
+++ b/embed/xulrunner/embed/EphyPromptService.cpp
@@ -0,0 +1,888 @@
+/*
+ * Copyright © 2005, 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <nsStringAPI.h>
+
+#include <nsCOMPtr.h>
+#include <nsIDOMWindow.h>
+#include <nsServiceManagerUtils.h>
+
+#include "ephy-embed-shell.h"
+#include "ephy-gui.h"
+#include "ephy-debug.h"
+
+#include "AutoJSContextStack.h"
+#include "AutoWindowModalState.h"
+#include "EphyUtils.h"
+
+#include "EphyPromptService.h"
+
+#define TIMEOUT 1000 /* ms */
+#define TIMEOUT_DATA_KEY "timeout"
+
+#define MAX_MESSAGE_LENGTH 512
+#define MAX_TITLE_LENGTH 256
+#define MAX_BUTTON_TEXT_LENGTH 128
+
+enum
+{
+ RESPONSE_ABORT_SCRIPT = 42
+};
+
+class Prompter
+{
+public:
+ Prompter (const char*, nsIDOMWindow*, const PRUnichar*, const PRUnichar*);
+ ~Prompter();
+
+ void AddStockButton (const char*, int);
+ void AddButtonWithFlags (PRInt32, PRUint32, const PRUnichar*, PRUint32);
+ void AddButtonsWithFlags (PRUint32, const PRUnichar*, const PRUnichar*, const PRUnichar*);
+ void AddCheckbox (const PRUnichar*, PRBool*);
+ void GetCheckboxState (PRBool *);
+ void AddEntry (const char *, const PRUnichar *, PRBool);
+ void GetText (PRUint32, PRUnichar **);
+ void AddSelect (PRUint32, const PRUnichar **, PRInt32);
+ void GetSelected (PRInt32*);
+
+ PRInt32 Run (PRBool * = nsnull);
+ void Show ();
+
+ PRBool IsCalledFromScript ();
+ void PerformScriptAbortion ();
+
+ char *ConvertAndTruncateString (const PRUnichar *, PRInt32 = -1);
+ char* ConvertAndEscapeButtonText (const PRUnichar *, PRInt32 = -1);
+
+private:
+ nsCOMPtr<nsIDOMWindow> mWindow;
+ GtkDialog *mDialog;
+ GtkWidget *mVBox;
+ GtkWidget *mCheck;
+ GtkSizeGroup *mSizeGroup;
+ GtkWidget *mEntries[2];
+ GtkWidget *mCombo;
+ PRInt32 mNumButtons;
+ PRInt32 mNumEntries;
+ PRInt32 mDefaultResponse;
+ PRInt32 mUnaffirmativeResponse;
+ PRInt32 mResponse;
+ PRBool mSuccess;
+ PRBool mDelay;
+};
+
+Prompter::Prompter (const char *aStock,
+ nsIDOMWindow *aParent,
+ const PRUnichar *aTitle,
+ const PRUnichar *aText)
+ : mWindow (aParent)
+ , mDialog(nsnull)
+ , mVBox(nsnull)
+ , mCheck(nsnull)
+ , mSizeGroup(nsnull)
+ , mCombo(nsnull)
+ , mNumButtons(0)
+ , mNumEntries(0)
+ , mDefaultResponse(GTK_RESPONSE_ACCEPT)
+ , mUnaffirmativeResponse(0)
+ , mResponse(GTK_RESPONSE_CANCEL)
+ , mSuccess(PR_FALSE)
+ , mDelay(PR_FALSE)
+{
+ GtkWidget *parent, *hbox, *label, *image;
+
+ g_object_ref (ephy_embed_shell_get_default ());
+
+ mEntries[0] = mEntries[1] = nsnull;
+
+ mDialog = GTK_DIALOG (gtk_dialog_new ());
+ g_object_ref_sink (mDialog);
+
+ char *title = NULL;
+ if (aTitle)
+ {
+ title = ConvertAndTruncateString (aTitle, MAX_TITLE_LENGTH);
+ }
+
+ gtk_window_set_title (GTK_WINDOW (mDialog), title ? title : "");
+ g_free (title);
+
+ gtk_window_set_modal (GTK_WINDOW (mDialog), TRUE);
+
+ parent = EphyUtils::FindGtkParent (aParent);
+ if (GTK_IS_WINDOW (parent))
+ {
+ gtk_window_set_transient_for (GTK_WINDOW (mDialog),
+ GTK_WINDOW (parent));
+
+ gtk_window_group_add_window (ephy_gui_ensure_window_group (GTK_WINDOW (parent)),
+ GTK_WINDOW (mDialog));
+ }
+
+ gtk_dialog_set_has_separator (mDialog, FALSE);
+ gtk_window_set_resizable (GTK_WINDOW (mDialog), FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (mDialog), 5);
+ gtk_box_set_spacing (GTK_BOX (mDialog->vbox), 14); /* 2 * 5 + 14 = 24 */
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (mDialog)->vbox), hbox);
+
+ image = gtk_image_new_from_stock (aStock, GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+
+ mVBox = gtk_vbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (hbox), mVBox, TRUE, TRUE, 0);
+
+ char *text = NULL;
+ if (aText)
+ {
+ text = ConvertAndTruncateString (aText, MAX_MESSAGE_LENGTH);
+ }
+
+ label = gtk_label_new (text);
+ g_free (text);
+
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ /* Guard against overlong nonbreakable text (exploit) */
+ gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR);
+ gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+
+ gtk_box_pack_start (GTK_BOX (mVBox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ if (IsCalledFromScript ())
+ {
+ gtk_dialog_add_button (GTK_DIALOG (mDialog),
+ _("_Abort Script"),
+ RESPONSE_ABORT_SCRIPT);
+ }
+
+ gtk_widget_show (image);
+ gtk_widget_show (mVBox);
+ gtk_widget_show (hbox);
+}
+
+Prompter::~Prompter ()
+{
+ if (mSizeGroup)
+ {
+ g_object_unref (mSizeGroup);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (mDialog));
+ g_object_unref (mDialog);
+
+ g_object_unref (ephy_embed_shell_get_default ());
+}
+
+void
+Prompter::AddStockButton (const char *aStock,
+ int aResponse)
+{
+ gtk_dialog_add_button (GTK_DIALOG (mDialog),
+ aStock, aResponse);
+ ++mNumButtons;
+}
+
+void
+Prompter::AddButtonWithFlags (PRInt32 aNum,
+ PRUint32 aFlags,
+ const PRUnichar *aText,
+ PRUint32 aDefault)
+{
+ if (aFlags == 0) return;
+
+ const char *label = NULL;
+ char *freeme = NULL;
+ gboolean isAffirmative = FALSE;
+ switch (aFlags)
+ {
+ case nsIPromptService::BUTTON_TITLE_OK:
+ label = GTK_STOCK_OK;
+ isAffirmative = TRUE;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_CANCEL:
+ label = GTK_STOCK_CANCEL;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_YES:
+ label = GTK_STOCK_YES;
+ isAffirmative = TRUE;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_NO:
+ label = GTK_STOCK_NO;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_SAVE:
+ label = GTK_STOCK_SAVE;
+ isAffirmative = TRUE;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_DONT_SAVE:
+ label = _("Don't Save");
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_REVERT:
+ label = GTK_STOCK_REVERT_TO_SAVED;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_IS_STRING:
+ default:
+ label = freeme = ConvertAndEscapeButtonText (aText, MAX_BUTTON_TEXT_LENGTH);
+ /* We can't tell, so assume it's affirmative */
+ isAffirmative = TRUE;
+ break;
+ }
+
+ if (label == NULL) return;
+
+ gtk_dialog_add_button (mDialog, label, aNum);
+ ++mNumButtons;
+
+ if (isAffirmative && mDelay)
+ {
+ gtk_dialog_set_response_sensitive (mDialog, aNum, FALSE);
+ }
+
+ if (!isAffirmative)
+ {
+ mUnaffirmativeResponse = aNum;
+ }
+
+ if (aDefault)
+ {
+ mDefaultResponse = aNum;
+ }
+
+ g_free (freeme);
+}
+
+void
+Prompter::AddButtonsWithFlags (PRUint32 aFlags,
+ const PRUnichar *aText0,
+ const PRUnichar *aText1,
+ const PRUnichar *aText2)
+{
+ mDelay = (aFlags & nsIPromptService::BUTTON_DELAY_ENABLE) != 0;
+ mDefaultResponse = -1;
+
+ /* Reverse the order, on the assumption that what we passed is the
+ * 'windows' button order, and we want HIG order.
+ */
+ AddButtonWithFlags (2, ((aFlags / nsIPromptService::BUTTON_POS_2) & 0xff), aText2,
+ aFlags & nsIPromptService::BUTTON_POS_2_DEFAULT);
+ AddButtonWithFlags (1, ((aFlags / nsIPromptService::BUTTON_POS_1) & 0xff), aText1,
+ aFlags & nsIPromptService::BUTTON_POS_1_DEFAULT);
+ AddButtonWithFlags (0, ((aFlags / nsIPromptService::BUTTON_POS_0) & 0xff), aText0,
+ aFlags & nsIPromptService::BUTTON_POS_0_DEFAULT);
+
+ /* If no default was set, use the 'rightmost' unaffirmative response.
+ * This happens with the suite's password manager prompt.
+ */
+ if (mDefaultResponse == -1)
+ {
+ mDefaultResponse = mUnaffirmativeResponse;
+ }
+}
+
+void
+Prompter::AddCheckbox (const PRUnichar *aText,
+ PRBool *aState)
+{
+ if (!aState || !aText) return;
+
+ char *label = ConvertAndEscapeButtonText (aText, 2 * MAX_BUTTON_TEXT_LENGTH);
+ mCheck = gtk_check_button_new_with_mnemonic (label);
+ g_free (label);
+
+ gtk_label_set_line_wrap (GTK_LABEL (GTK_BIN (mCheck)->child), TRUE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mCheck), *aState);
+ gtk_box_pack_start (GTK_BOX (mVBox), mCheck, FALSE, FALSE, 0);
+ gtk_widget_show (mCheck);
+}
+
+void
+Prompter::GetCheckboxState (PRBool *aState)
+{
+ if (!aState || !mCheck) return;
+
+ *aState = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mCheck));
+}
+
+void
+Prompter::AddEntry (const char *aLabel,
+ const PRUnichar *aValue,
+ PRBool aIsPassword)
+{
+ if (!mSizeGroup)
+ {
+ mSizeGroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ }
+
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (mVBox), hbox, FALSE, FALSE, 0);
+
+ GtkWidget *label = nsnull;
+ if (aLabel)
+ {
+ label = gtk_label_new_with_mnemonic (aLabel);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_size_group_add_widget (mSizeGroup, label);
+ }
+
+ GtkWidget *entry = mEntries[mNumEntries++] = gtk_entry_new ();
+ gtk_entry_set_visibility (GTK_ENTRY (entry), !aIsPassword);
+ gtk_entry_set_activates_default(GTK_ENTRY (entry), TRUE);
+
+ if (aValue)
+ {
+ nsCString cValue;
+ NS_UTF16ToCString (nsDependentString(aValue),
+ NS_CSTRING_ENCODING_UTF8, cValue);
+
+ gtk_entry_set_text (GTK_ENTRY (entry), cValue.get());
+ }
+
+ if (label)
+ {
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+ }
+
+ gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+}
+
+void
+Prompter::GetText (PRUint32 aNum,
+ PRUnichar **aValue)
+{
+ if (!aValue || !mEntries[aNum]) return;
+
+ const char *text = gtk_entry_get_text (GTK_ENTRY (mEntries[aNum]));
+ if (!text) return;
+
+ nsString value;
+ NS_CStringToUTF16 (nsDependentCString (text),
+ NS_CSTRING_ENCODING_UTF8, value);
+
+ *aValue = NS_StringCloneData (value);
+}
+
+void
+Prompter::AddSelect (PRUint32 aCount,
+ const PRUnichar **aList,
+ PRInt32 aDefault)
+{
+ mCombo = gtk_combo_box_new_text ();
+
+ for (PRUint32 i = 0; i < aCount; i++)
+ {
+ /* FIXME: use "" instead in this case? */
+ if (!aList[i] || !aList[i][0]) continue;
+
+ nsCString cData;
+ NS_UTF16ToCString (nsDependentString(aList[i]), NS_CSTRING_ENCODING_UTF8, cData);
+
+ gtk_combo_box_append_text (GTK_COMBO_BOX (mCombo), cData.get());
+ }
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (mCombo), aDefault);
+
+ gtk_box_pack_start (GTK_BOX (mVBox), mCombo, FALSE, FALSE, 0);
+ gtk_widget_show (mCombo);
+}
+
+void
+Prompter::GetSelected (PRInt32 *aSelected)
+{
+ if (!aSelected || !mCombo) return;
+
+ *aSelected = gtk_combo_box_get_active (GTK_COMBO_BOX (mCombo));
+}
+
+static gboolean
+EnableResponse (GtkDialog *aDialog)
+{
+ g_object_steal_data (G_OBJECT (aDialog), TIMEOUT_DATA_KEY);
+
+ gtk_dialog_set_response_sensitive (aDialog, 0, TRUE);
+ gtk_dialog_set_response_sensitive (aDialog, 1, TRUE);
+ gtk_dialog_set_response_sensitive (aDialog, 2, TRUE);
+
+ return FALSE;
+}
+
+static void
+RemoveTimeout (gpointer idptr)
+{
+ guint timeout = GPOINTER_TO_UINT (idptr);
+
+ g_return_if_fail (timeout != 0);
+
+ g_source_remove (timeout);
+}
+
+PRInt32
+Prompter::Run (PRBool *aSuccess)
+{
+#if 0
+ AutoEventQueue queue;
+ if (NS_FAILED (queue.Init()))
+ {
+ if (aSuccess)
+ {
+ *aSuccess = PR_FALSE;
+ }
+ mSuccess = PR_FALSE;
+
+ return GTK_RESPONSE_CANCEL;
+ }
+#endif
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ AutoWindowModalState modalState (mWindow);
+
+ if (mDelay)
+ {
+ guint timeout = g_timeout_add (TIMEOUT,
+ (GSourceFunc) EnableResponse,
+ mDialog);
+ g_object_set_data_full (G_OBJECT (mDialog), TIMEOUT_DATA_KEY,
+ GUINT_TO_POINTER (timeout),
+ (GDestroyNotify) RemoveTimeout);
+ }
+
+ gtk_dialog_set_default_response (GTK_DIALOG (mDialog), mDefaultResponse);
+
+ GtkWidget *widget = GTK_WIDGET (mDialog);
+ gtk_widget_show (widget);
+ mResponse = gtk_dialog_run (mDialog);
+ gtk_widget_hide (widget);
+
+ g_object_set_data (G_OBJECT (mDialog), TIMEOUT_DATA_KEY, NULL);
+
+ mSuccess = (GTK_RESPONSE_ACCEPT == mResponse);
+ if (aSuccess)
+ {
+ *aSuccess = mSuccess;
+ }
+
+ if (mResponse == RESPONSE_ABORT_SCRIPT)
+ {
+ PerformScriptAbortion ();
+ }
+
+ return mResponse;
+}
+
+static void
+DeletePrompter (gpointer aPromptPtr,
+ GObject *aZombie)
+{
+ Prompter *prompt = static_cast<Prompter*>(aPromptPtr);
+
+ delete prompt;
+}
+
+void
+Prompter::Show ()
+{
+ /* We don't need it anymore */
+ mWindow = nsnull;
+
+ gtk_window_set_modal (GTK_WINDOW (mDialog), FALSE);
+
+ g_signal_connect (mDialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ g_object_weak_ref (G_OBJECT (mDialog),
+ (GWeakNotify) DeletePrompter,
+ static_cast<gpointer>(this));
+
+ gtk_widget_show (GTK_WIDGET (mDialog));
+}
+
+PRBool
+Prompter::IsCalledFromScript()
+{
+#if 0
+ nsCOMPtr<nsIXPConnect> xpconnect (do_GetService (nsIXPConnect::GetCID()));
+ NS_ENSURE_TRUE (xpconnect, PR_FALSE);
+
+ nsresult rv;
+ nsCOMPtr<nsIXPCNativeCallContext> ncc;
+ rv = xpconnect->GetCurrentNativeCallContext (getter_AddRefs (ncc));
+ NS_ENSURE_SUCCESS (rv, PR_FALSE);
+
+ if (!ncc) return PR_FALSE;
+
+ JSContext *cx = nsnull;
+ rv = ncc->GetJSContext (&cx);
+ g_print ("GetJSContext rv=%x, cx=%p\n", rv, cx);
+
+ NS_ENSURE_SUCCESS (rv, PR_FALSE);
+
+ return cx != nsnull;
+#endif
+ return PR_FALSE;
+}
+
+void
+Prompter::PerformScriptAbortion()
+{
+#if 0
+ /* FIXME: can we only stop the calling script, not all scripts in the context? */
+
+ nsCOMPtr<nsIXPConnect> xpconnect (do_GetService (nsIXPConnect::GetCID()));
+ NS_ENSURE_TRUE (xpconnect, );
+
+ nsresult rv;
+ nsCOMPtr<nsIXPCNativeCallContext> ncc;
+ rv = xpconnect->GetCurrentNativeCallContext (getter_AddRefs (ncc));
+ NS_ENSURE_SUCCESS (rv, );
+ NS_ENSURE_TRUE (ncc, );
+
+ JSContext *cx = nsnull;
+ rv = ncc->GetJSContext (&cx);
+ g_print ("GetJSContext rv=%x, cx=%p\n", rv, cx);
+ NS_ENSURE_SUCCESS (rv, );
+ NS_ENSURE_TRUE (cx, );
+
+ g_print ("Would now disable scripts\n");
+// MozillaPrivate::SetScriptsEnabled (cx, PR_FALSE, PR_FALSE);
+#endif
+}
+
+char *
+Prompter::ConvertAndTruncateString (const PRUnichar *aText,
+ PRInt32 aMaxLength)
+{
+ if (aText == nsnull) return NULL;
+
+ /* This depends on the assumption that
+ * typeof(PRUnichar) == typeof (gunichar2) == uint16,
+ * which should be pretty safe.
+ */
+ glong n_read = 0, n_written = 0;
+ char *converted = g_utf16_to_utf8 ((gunichar2*) aText, aMaxLength,
+ &n_read, &n_written, NULL);
+ /* FIXME loop from the end while !g_unichar_isspace (char)? */
+
+ return converted;
+}
+
+char *
+Prompter::ConvertAndEscapeButtonText(const PRUnichar *aText,
+ PRInt32 aMaxLength)
+{
+ char *converted = ConvertAndTruncateString (aText, aMaxLength);
+ if (converted == NULL) return NULL;
+
+ char *escaped = (char*) g_malloc (strlen (converted) + 1);
+ char *q = escaped;
+ for (const char *p = converted; *p; ++p, ++q)
+ {
+ if (*p == '&')
+ {
+ if (*(p+1) == '&')
+ {
+ *q = '&';
+ ++p;
+ }
+ else
+ {
+ *q = '_';
+ }
+ }
+ else
+ {
+ *q = *p;
+ }
+ }
+
+ /* Null termination */
+ *q = '\0';
+
+ g_free (converted);
+
+ return escaped;
+}
+
+/* FIXME: needs THREADSAFE? */
+#if HAVE_NSINONBLOCKINGALERTSERVICE_H
+NS_IMPL_ISUPPORTS2 (EphyPromptService,
+ nsIPromptService,
+ nsINonBlockingAlertService)
+#else
+NS_IMPL_ISUPPORTS1 (EphyPromptService,
+ nsIPromptService)
+#endif
+
+EphyPromptService::EphyPromptService()
+{
+ LOG ("EphyPromptService ctor (%p)", this);
+}
+
+EphyPromptService::~EphyPromptService()
+{
+ LOG ("EphyPromptService dtor (%p)", this);
+}
+
+/* nsIPromptService implementation */
+
+/* void alert (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText); */
+NS_IMETHODIMP
+EphyPromptService::Alert (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText)
+{
+ Prompter prompt (GTK_STOCK_DIALOG_INFO, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.Run ();
+
+ return NS_OK;
+}
+
+/* void alertCheck (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+EphyPromptService::AlertCheck (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState)
+{
+ Prompter prompt (GTK_STOCK_DIALOG_INFO, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ prompt.Run ();
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* boolean confirm (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText); */
+NS_IMETHODIMP
+EphyPromptService::Confirm (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+
+ Prompter prompt (GTK_STOCK_DIALOG_QUESTION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.Run (_retval);
+
+ return NS_OK;
+}
+
+/* boolean confirmCheck (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+EphyPromptService::ConfirmCheck (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+
+ Prompter prompt (GTK_STOCK_DIALOG_QUESTION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ prompt.Run (_retval);
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* PRInt32 confirmEx (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, in unsigned long aButtonFlags, in wstring aButton0Title, in wstring aButton1Title, in wstring aButton2Title, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+EphyPromptService::ConfirmEx (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRUint32 aButtonFlags,
+ const PRUnichar *aButton0Title,
+ const PRUnichar *aButton1Title,
+ const PRUnichar *aButton2Title,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState,
+ PRInt32 *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+
+ Prompter prompt (GTK_STOCK_DIALOG_QUESTION, aParent, aDialogTitle, aText);
+ prompt.AddButtonsWithFlags (aButtonFlags, aButton0Title,
+ aButton1Title, aButton2Title);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ *_retval = prompt.Run (nsnull);
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* boolean prompt (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, inout wstring aValue, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+EphyPromptService::Prompt (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRUnichar **aValue,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+ NS_ENSURE_ARG_POINTER (aValue);
+
+ Prompter prompt (GTK_STOCK_DIALOG_QUESTION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddEntry (nsnull, *aValue, PR_FALSE);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ prompt.Run (_retval);
+ prompt.GetText (0, aValue);
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* boolean promptUsernameAndPassword (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, inout wstring aUsername, inout wstring aPassword, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+EphyPromptService::PromptUsernameAndPassword (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRUnichar **aUsername,
+ PRUnichar **aPassword,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+ NS_ENSURE_ARG_POINTER (aUsername);
+ NS_ENSURE_ARG_POINTER (aPassword);
+
+ Prompter prompt (GTK_STOCK_DIALOG_AUTHENTICATION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddEntry (_("_Username:"), *aUsername, PR_FALSE);
+ prompt.AddEntry (_("_Password:"), *aPassword, PR_TRUE);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ prompt.Run (_retval);
+ prompt.GetText (0, aUsername);
+ prompt.GetText (1, aPassword);
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* boolean promptPassword (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, inout wstring aPassword, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+EphyPromptService::PromptPassword (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRUnichar **aPassword,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+ NS_ENSURE_ARG_POINTER (aPassword);
+
+ Prompter prompt (GTK_STOCK_DIALOG_AUTHENTICATION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddEntry (_("_Password:"), *aPassword, PR_TRUE);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ // FIXME: Add a CAPSLOCK indicator?
+
+ prompt.Run (_retval);
+ prompt.GetText (0, aPassword);
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* boolean select (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, in PRUint32 aCount, [array, size_is (aCount)] in wstring aSelectList, out long aOutSelection); */
+NS_IMETHODIMP
+EphyPromptService::Select (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRUint32 aCount,
+ const PRUnichar **aSelectList,
+ PRInt32 *aOutSelection,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+ NS_ENSURE_ARG_POINTER (aOutSelection);
+
+ Prompter prompt (GTK_STOCK_DIALOG_QUESTION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddSelect (aCount, aSelectList, *aOutSelection);
+
+ prompt.Run (_retval);
+ prompt.GetSelected (aOutSelection);
+
+ return NS_OK;
+}
+
+#if HAVE_NSINONBLOCKINGALERTSERVICE_H
+
+/* showNonBlockingAlert (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText); */
+NS_IMETHODIMP
+EphyPromptService::ShowNonBlockingAlert (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText)
+{
+ Prompter *prompt = new Prompter (GTK_STOCK_DIALOG_INFO, aParent, aDialogTitle, aText);
+ if (!prompt) return NS_ERROR_OUT_OF_MEMORY;
+
+ prompt->AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt->Show ();
+
+ return NS_OK;
+}
+
+#endif /* HAVE_NSINONBLOCKINGALERTSERVICE_H */
diff --git a/embed/xulrunner/embed/EphyPromptService.h b/embed/xulrunner/embed/EphyPromptService.h
new file mode 100644
index 000000000..2416e5318
--- /dev/null
+++ b/embed/xulrunner/embed/EphyPromptService.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2005, 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_PROMPT_SERVICE_H
+#define EPHY_PROMPT_SERVICE_H
+
+#include <nsIPromptService.h>
+
+#if HAVE_NSINONBLOCKINGALERTSERVICE_H
+#include <nsINonBlockingAlertService.h>
+#endif
+
+#define EPHY_PROMPT_SERVICE_IID \
+{ /* 6e8b90d4-78a6-41c5-98da-b1559a40d30d */ \
+ 0x6e8b90d4, 0x78a6, 0x41c5, \
+ { 0x98, 0xda, 0xb1, 0x55, 0x9a, 0x40, 0xd3, 0x0d } }
+
+#define EPHY_PROMPT_SERVICE_CLASSNAME "Epiphany Prompt Service"
+
+class EphyPromptService : public nsIPromptService
+#if HAVE_NSINONBLOCKINGALERTSERVICE_H
+ , public nsINonBlockingAlertService
+#endif
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROMPTSERVICE
+#if HAVE_NSINONBLOCKINGALERTSERVICE_H
+ NS_DECL_NSINONBLOCKINGALERTSERVICE
+#endif
+
+ EphyPromptService();
+ virtual ~EphyPromptService();
+};
+
+#endif /* EPHY_PROMPT_SERVICE_H */
diff --git a/embed/xulrunner/embed/EphyRedirectChannel.cpp b/embed/xulrunner/embed/EphyRedirectChannel.cpp
new file mode 100644
index 000000000..6e493bfad
--- /dev/null
+++ b/embed/xulrunner/embed/EphyRedirectChannel.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2005 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include "EphyRedirectChannel.h"
+
+NS_IMPL_ISUPPORTS2 (EphyWrappedChannel, nsIRequest, nsIChannel)
+
+NS_IMETHODIMP
+EphyRedirectChannel::SetLoadFlags(nsLoadFlags aFlags)
+{
+ return mChannel->SetLoadFlags (aFlags | LOAD_REPLACE);
+}
diff --git a/embed/xulrunner/embed/EphyRedirectChannel.h b/embed/xulrunner/embed/EphyRedirectChannel.h
new file mode 100644
index 000000000..bcec1f1e5
--- /dev/null
+++ b/embed/xulrunner/embed/EphyRedirectChannel.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2005 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_REDIRECT_CHANNEL_H
+#define EPHY_REDIRECT_CHANNEL_H
+
+#include <nsCOMPtr.h>
+#include <nsIChannel.h>
+
+class EphyWrappedChannel : public nsIChannel
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_FORWARD_NSIREQUEST (mChannel->)
+ NS_FORWARD_NSICHANNEL (mChannel->)
+
+ EphyWrappedChannel (nsIChannel *aChannel) : mChannel (aChannel) { }
+ virtual ~EphyWrappedChannel () { }
+
+ protected:
+ nsCOMPtr<nsIChannel> mChannel;
+};
+
+class EphyRedirectChannel : public EphyWrappedChannel
+{
+ public:
+ EphyRedirectChannel (nsIChannel *aChannel) : EphyWrappedChannel (aChannel) { }
+ virtual ~EphyRedirectChannel () { }
+
+ NS_IMETHOD SetLoadFlags (nsLoadFlags aFlags);
+};
+
+#endif /* !EPHY_REDIRECT_CHANNEL_H */
diff --git a/embed/xulrunner/embed/EphySidebar.cpp b/embed/xulrunner/embed/EphySidebar.cpp
new file mode 100644
index 000000000..94bd52b8a
--- /dev/null
+++ b/embed/xulrunner/embed/EphySidebar.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright © 2002 Philip Langdale
+ * Copyright © 2004 Crispin Flowerday
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <nsStringAPI.h>
+
+#include <nsICategoryManager.h>
+#include <nsIScriptNameSpaceManager.h>
+#include <nsMemory.h>
+#include <nsServiceManagerUtils.h>
+#include <nsXPCOMCID.h>
+
+#ifdef HAVE_GECKO_1_9
+#include <nsIClassInfoImpl.h>
+#endif
+
+#include "ephy-debug.h"
+#include "ephy-embed-shell.h"
+#include "ephy-embed-single.h"
+
+#include "EphySidebar.h"
+
+NS_IMPL_ISUPPORTS1_CI(EphySidebar, nsISidebar)
+
+EphySidebar::EphySidebar()
+{
+}
+
+EphySidebar::~EphySidebar()
+{
+}
+
+/* void addPanel (in wstring aTitle, in string aContentURL, in string aCustomizeURL); */
+NS_IMETHODIMP
+EphySidebar::AddPanel (const PRUnichar *aTitle,
+ const char *aContentURL,
+ const char *aCustomizeURL)
+{
+ NS_ENSURE_ARG (aTitle);
+ NS_ENSURE_ARG (aContentURL);
+
+ nsCString title;
+ EphyEmbedSingle *single;
+
+ /* FIXME: length-limit string */
+ NS_UTF16ToCString (nsDependentString(aTitle),
+ NS_CSTRING_ENCODING_UTF8, title);
+
+ LOG ("Adding sidebar, url=%s title=%s", aContentURL, title.get());
+
+ single = EPHY_EMBED_SINGLE (ephy_embed_shell_get_embed_single (embed_shell));
+
+ gboolean result = FALSE;
+ g_signal_emit_by_name (single, "add-sidebar",
+ aContentURL, title.get(), &result);
+
+ return NS_OK;
+}
+
+/* void addPersistentPanel (in wstring aTitle, in string aContentURL, in string aCustomizeURL); */
+NS_IMETHODIMP
+EphySidebar::AddPersistentPanel (const PRUnichar *aTitle,
+ const char *aContentURL,
+ const char *aCustomizeURL)
+{
+ return AddPanel (aTitle, aContentURL, aCustomizeURL);
+}
+
+/* void addSearchEngine (in string engineURL, in string iconURL, in wstring suggestedTitle, in wst
+ring suggestedCategory); */
+NS_IMETHODIMP
+EphySidebar::AddSearchEngine (const char *aEngineURL,
+ const char *aIconURL,
+ const PRUnichar *aSuggestedTitle,
+ const PRUnichar *aSuggestedCategory)
+{
+ NS_ENSURE_ARG (aSuggestedTitle);
+ NS_ENSURE_ARG (aIconURL);
+ NS_ENSURE_ARG (aEngineURL);
+
+ nsCString title;
+ EphyEmbedSingle *single;
+
+ /* FIXME: length-limit string */
+ NS_UTF16ToCString (nsDependentString(aSuggestedTitle),
+ NS_CSTRING_ENCODING_UTF8, title);
+
+ LOG ("Adding search engine, engineurl=%s iconurl=%s title=%s", aEngineURL, aIconURL, title.get());
+
+ single = EPHY_EMBED_SINGLE (ephy_embed_shell_get_embed_single (embed_shell));
+
+ gboolean result = FALSE;
+ g_signal_emit_by_name (single, "add-search-engine",
+ aEngineURL, aIconURL, title.get(), &result);
+
+ return NS_OK;
+}
+
+#ifdef HAVE_GECKO_1_9
+
+/* void addMicrosummaryGenerator (in string generatorURL); */
+NS_IMETHODIMP
+EphySidebar::AddMicrosummaryGenerator (const char *generatorURL)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#endif /* HAVE_GECKO_1_9 */
+
+/* static */ NS_METHOD
+EphySidebar::Register (nsIComponentManager* aComponentManager,
+ nsIFile* aPath,
+ const char* aRegistryLocation,
+ const char* aComponentType,
+ const nsModuleComponentInfo* aInfo)
+{
+ nsresult rv;
+ nsCOMPtr<nsICategoryManager> catMan (do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = catMan->AddCategoryEntry (JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY,
+ "sidebar",
+ NS_SIDEBAR_CONTRACTID,
+ PR_FALSE /* don't persist */,
+ PR_TRUE /* replace */,
+ nsnull);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ return rv;
+}
+
+/* static */ NS_METHOD
+EphySidebar::Unregister (nsIComponentManager* aComponentManager,
+ nsIFile* aPath,
+ const char* aRegistryLocation,
+ const nsModuleComponentInfo* aInfo)
+{
+ nsresult rv;
+ nsCOMPtr<nsICategoryManager> catMan (do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = catMan->DeleteCategoryEntry (JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY,
+ "sidebar",
+ PR_FALSE /* don't persist */);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ return rv;
+}
diff --git a/embed/xulrunner/embed/EphySidebar.h b/embed/xulrunner/embed/EphySidebar.h
new file mode 100644
index 000000000..37efa0bf8
--- /dev/null
+++ b/embed/xulrunner/embed/EphySidebar.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2002 Philip Langdale
+ * Copyright © 2004 Crispin Flowerday
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_SIDEBAR_H
+#define EPHY_SIDEBAR_H
+
+#include <nsISidebar.h>
+
+class nsIComponentManager;
+class nsIFile;
+struct nsModuleComponentInfo;
+
+#define EPHY_SIDEBAR_CLASSNAME \
+ "Epiphany's Sidebar Implementation"
+
+#define EPHY_SIDEBAR_CID \
+{ /* {50f13159-f9b9-44b3-b18e-6ee5d85a202a} */ \
+ 0x50f13159, \
+ 0xf9b9, \
+ 0x44b3, \
+ {0xb1, 0x8e, 0x6e, 0xe5, 0xd8, 0x5a, 0x20, 0x2a} \
+}
+
+class EphySidebar : public nsISidebar
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIDEBAR
+
+ EphySidebar();
+
+ static NS_METHOD Register (nsIComponentManager* aComponentManager,
+ nsIFile* aPath,
+ const char* aRegistryLocation,
+ const char* aComponentType,
+ const nsModuleComponentInfo* aInfo);
+
+ static NS_METHOD Unregister (nsIComponentManager* aComponentManager,
+ nsIFile* aPath,
+ const char* aRegistryLocation,
+ const nsModuleComponentInfo* aInfo);
+
+ private:
+ ~EphySidebar();
+};
+
+#endif /* ! EPHY_SIDEBAR_H */
+
diff --git a/embed/xulrunner/embed/EphySingle.cpp b/embed/xulrunner/embed/EphySingle.cpp
new file mode 100644
index 000000000..74eaf21d6
--- /dev/null
+++ b/embed/xulrunner/embed/EphySingle.cpp
@@ -0,0 +1,396 @@
+/*
+ * Copyright © 2003 Christian Persch
+ * Copyright © 2003 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <nsStringAPI.h>
+
+#include <nsICookie.h>
+#include <nsICookie2.h>
+#include <nsICookieManager.h>
+#include <nsIHttpChannel.h>
+#include <nsIObserverService.h>
+#include <nsIPermission.h>
+#include <nsIPermissionManager.h>
+#include <nsIPropertyBag2.h>
+#include <nsIServiceManager.h>
+#include <nsIURI.h>
+#include <nsServiceManagerUtils.h>
+#include <nsWeakReference.h>
+
+#ifdef ALLOW_PRIVATE_API
+#include <nsIIDNService.h>
+#endif
+
+#include "ephy-debug.h"
+
+#include "EphySingle.h"
+
+NS_IMPL_ISUPPORTS1(EphySingle, nsIObserver)
+
+EphySingle::EphySingle()
+: mOwner(nsnull)
+, mIsOnline(PR_TRUE) /* nsIOService doesn't send an initial notification, assume we start on-line */
+{
+ LOG ("EphySingle ctor");
+}
+
+nsresult
+EphySingle::Init (EphyEmbedSingle *aOwner)
+{
+ mObserverService = do_GetService ("@mozilla.org/observer-service;1");
+ NS_ENSURE_TRUE (mObserverService, NS_ERROR_FAILURE);
+
+ nsresult rv;
+ rv = mObserverService->AddObserver (this, "cookie-changed", PR_FALSE);
+ rv |= mObserverService->AddObserver (this, "cookie-rejected", PR_FALSE);
+ rv |= mObserverService->AddObserver (this, "perm-changed", PR_FALSE);
+ rv |= mObserverService->AddObserver (this, "network:offline-status-changed", PR_FALSE);
+ rv |= mObserverService->AddObserver (this, "signonChanged", PR_FALSE);
+ rv |= mObserverService->AddObserver (this, "http-on-examine-response", PR_FALSE);
+ rv |= mObserverService->AddObserver (this, "http-on-modify-request", PR_FALSE);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ mOwner = aOwner;
+
+ LOG ("EphySingle::Init");
+
+ return NS_OK;
+}
+
+nsresult
+EphySingle::Detach ()
+{
+ LOG ("EphySingle::Detach");
+
+ if (mObserverService)
+ {
+ mObserverService->RemoveObserver (this, "cookie-changed");
+ mObserverService->RemoveObserver (this, "cookie-rejected");
+ mObserverService->RemoveObserver (this, "perm-changed");
+ mObserverService->RemoveObserver (this, "signonChanged");
+ mObserverService->RemoveObserver (this, "network:offline-status-changed");
+ mObserverService->RemoveObserver (this, "http-on-examine-response");
+ mObserverService->RemoveObserver (this, "http-on-modify-request");
+
+#if 1
+ /* HACK: Work around https://bugzilla.mozilla.org/show_bug.cgi?id=292699 */
+ mObserverService->NotifyObservers(nsnull, "profile-change-net-teardown", nsnull);
+#endif
+ }
+
+ return NS_OK;
+}
+
+EphySingle::~EphySingle()
+{
+ LOG ("EphySingle dtor");
+
+ mOwner = nsnull;
+}
+
+nsresult
+EphySingle::EmitCookieNotification (const char *name,
+ nsISupports *aSubject)
+{
+ LOG ("EmitCookieNotification %s", name);
+
+ nsCOMPtr<nsICookie> cookie = do_QueryInterface (aSubject);
+ NS_ENSURE_TRUE (cookie, NS_ERROR_FAILURE);
+
+ EphyCookie *info = mozilla_cookie_to_ephy_cookie (cookie);
+
+ g_signal_emit_by_name (EPHY_COOKIE_MANAGER (mOwner), name, info);
+
+ ephy_cookie_free (info);
+
+ return NS_OK;
+}
+
+nsresult
+EphySingle::EmitPermissionNotification (const char *name,
+ nsISupports *aSubject)
+{
+ LOG ("EmitPermissionNotification %s", name);
+
+ nsCOMPtr<nsIPermission> perm = do_QueryInterface (aSubject);
+ NS_ENSURE_TRUE (perm, NS_ERROR_FAILURE);
+
+ EphyPermissionInfo *info =
+ mozilla_permission_to_ephy_permission (perm);
+
+ g_signal_emit_by_name (EPHY_PERMISSION_MANAGER (mOwner), name, info);
+
+ ephy_permission_info_free (info);
+
+ return NS_OK;
+}
+
+nsresult
+EphySingle::ExamineCookies (nsISupports *aSubject)
+{
+ PRBool isBlockingCookiesChannel = PR_FALSE;
+
+ nsCOMPtr<nsIPropertyBag2> props (do_QueryInterface(aSubject));
+ if (props &&
+ NS_SUCCEEDED (props->GetPropertyAsBool(
+ NS_LITERAL_STRING("epiphany-blocking-cookies"),
+ &isBlockingCookiesChannel)) &&
+ isBlockingCookiesChannel)
+ {
+ nsCOMPtr<nsIHttpChannel> httpChannel (do_QueryInterface(aSubject));
+
+ if (httpChannel)
+ httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Cookie"),
+ EmptyCString(), PR_FALSE);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+EphySingle::ExamineResponse (nsISupports *aSubject)
+{
+ return ExamineCookies (aSubject);
+}
+
+nsresult
+EphySingle::ExamineRequest (nsISupports *aSubject)
+{
+ return ExamineCookies (aSubject);
+}
+
+/* void observe (in nsISupports aSubject, in string aTopic, in wstring aData); */
+NS_IMETHODIMP EphySingle::Observe(nsISupports *aSubject,
+ const char *aTopic,
+ const PRUnichar *aData)
+{
+ nsresult rv = NS_OK;
+
+ LOG ("EphySingle::Observe topic %s", aTopic);
+
+ if (strcmp (aTopic, "http-on-examine-response") == 0)
+ {
+ rv = ExamineResponse (aSubject);
+ }
+ else if (strcmp (aTopic, "http-on-modify-request") == 0)
+ {
+ rv = ExamineRequest (aSubject);
+ }
+ else if (strcmp (aTopic, "cookie-changed") == 0)
+ {
+ /* "added" */
+ if (aData[0] == 'a')
+ {
+ rv = EmitCookieNotification ("cookie-added", aSubject);
+ }
+ /* "deleted" */
+ else if (aData[0] == 'd')
+ {
+ rv = EmitCookieNotification ("cookie-deleted", aSubject);
+ }
+ /* "changed" */
+ else if (aData[0] == 'c' && aData[1] == 'h')
+ {
+ rv = EmitCookieNotification ("cookie-changed", aSubject);
+ }
+ /* "cleared" */
+ else if (aData[0] == 'c' && aData[1] == 'l')
+ {
+ LOG ("EphySingle::cookie-changed::cleared");
+
+ g_signal_emit_by_name (EPHY_COOKIE_MANAGER (mOwner), "cookies-cleared");
+ }
+ else
+ {
+ g_warning ("EphySingle unexpected data!\n");
+ rv = NS_ERROR_FAILURE;
+ }
+ }
+ else if (strcmp (aTopic, "cookie-rejected") == 0)
+ {
+ LOG ("EphySingle::cookie-rejected");
+
+ nsCOMPtr<nsIURI> uri = do_QueryInterface (aSubject);
+ if (uri)
+ {
+ nsCString spec;
+ uri->GetSpec (spec);
+
+ g_signal_emit_by_name (EPHY_COOKIE_MANAGER (mOwner), "cookie-rejected", spec.get());
+ }
+ else
+ {
+ rv = NS_ERROR_FAILURE;
+ }
+ }
+ else if (strcmp (aTopic, "perm-changed") == 0)
+ {
+ /* "added" */
+ if (aData[0] == 'a')
+ {
+ rv = EmitPermissionNotification ("permission-added", aSubject);
+ }
+ /* "deleted" */
+ else if (aData[0] == 'd')
+ {
+ rv = EmitPermissionNotification ("permission-deleted", aSubject);
+ }
+ /* "changed" */
+ else if (aData[0] == 'c' && aData[1] == 'h')
+ {
+ rv = EmitPermissionNotification ("permission-changed", aSubject);
+ }
+ /* "cleared" */
+ else if (aData[0] == 'c' && aData[1] == 'l')
+ {
+ LOG ("EphySingle::perm-changed::cleared");
+
+ g_signal_emit_by_name (EPHY_PERMISSION_MANAGER (mOwner), "permissions-cleared");
+ }
+ else
+ {
+ g_warning ("EphySingle unexpected data!\n");
+ rv = NS_ERROR_FAILURE;
+ }
+ }
+ else if (strcmp (aTopic, "signonChanged") == 0)
+ {
+ /* aData can be PRUnichar[] "signons", "rejects", "nocaptures" and "nopreviews" */
+ if (aData[0] == 's')
+ {
+ g_signal_emit_by_name (mOwner, "passwords-changed");
+ }
+ }
+ else if (strcmp (aTopic, "network:offline-status-changed") == 0)
+ {
+ /* aData is either (PRUnichar[]) "offline" or "online" */
+ mIsOnline = (aData && aData[0] == 'o' && aData[1] == 'n');
+
+ g_object_notify (G_OBJECT (mOwner), "network-status");
+ }
+ else
+ {
+ g_warning ("EphySingle observed unknown topic '%s'!\n", aTopic);
+ rv = NS_ERROR_FAILURE;
+ }
+
+ LOG ("EphySingle::Observe %s", NS_SUCCEEDED (rv) ? "success" : "FAILURE");
+
+ return rv;
+}
+
+EphyCookie *
+mozilla_cookie_to_ephy_cookie (nsICookie *cookie)
+{
+ EphyCookie *info;
+
+ nsCString transfer;
+
+ cookie->GetHost (transfer);
+
+ nsCOMPtr<nsIIDNService> idnService
+ (do_GetService ("@mozilla.org/network/idn-service;1"));
+ NS_ENSURE_TRUE (idnService, nsnull);
+
+ nsCString decoded;
+ /* ToUTF8 never fails, no need to check return value */
+ idnService->ConvertACEtoUTF8 (transfer, decoded);
+
+ info = ephy_cookie_new ();
+ info->domain = g_strdup (decoded.get());
+
+ cookie->GetName (transfer);
+ info->name = g_strdup (transfer.get());
+ cookie->GetValue (transfer);
+ info->value = g_strdup (transfer.get());
+ cookie->GetPath (transfer);
+ info->path = g_strdup (transfer.get());
+
+ PRBool isSecure;
+ cookie->GetIsSecure (&isSecure);
+ info->is_secure = isSecure != PR_FALSE;
+
+ PRUint64 dateTime;
+ cookie->GetExpires (&dateTime);
+ info->expires = dateTime;
+
+ nsCOMPtr<nsICookie2> cookie2 = do_QueryInterface (cookie);
+ NS_ENSURE_TRUE (cookie2, info);
+
+ PRBool isSession;
+ cookie2->GetIsSession (&isSession);
+ info->is_session = isSession != PR_FALSE;
+
+ if (!isSession)
+ {
+ PRInt64 expiry;
+ cookie2->GetExpiry (&expiry);
+ info->real_expires = expiry;
+ }
+
+#ifdef HAVE_GECKO_1_9
+ PRBool isHttpOnly = PR_FALSE;
+ cookie2->GetIsHttpOnly (&isHttpOnly);
+ info->is_http_only = isHttpOnly != PR_FALSE;
+#endif
+
+ return info;
+}
+
+EphyPermissionInfo *
+mozilla_permission_to_ephy_permission (nsIPermission *perm)
+{
+ nsresult rv;
+ nsCString type;
+ rv = perm->GetType(type);
+ NS_ENSURE_SUCCESS (rv, NULL);
+
+ PRUint32 cap;
+ perm->GetCapability(&cap);
+ EphyPermission permission;
+ switch (cap)
+ {
+ case nsIPermissionManager::ALLOW_ACTION:
+ permission = EPHY_PERMISSION_ALLOWED;
+ break;
+ case nsIPermissionManager::DENY_ACTION:
+ permission = EPHY_PERMISSION_DENIED;
+ break;
+ case nsIPermissionManager::UNKNOWN_ACTION:
+ default :
+ permission = EPHY_PERMISSION_DEFAULT;
+ break;
+ }
+
+ nsCString host;
+ perm->GetHost(host);
+
+ nsCOMPtr<nsIIDNService> idnService
+ (do_GetService ("@mozilla.org/network/idn-service;1"));
+ NS_ENSURE_TRUE (idnService, nsnull);
+
+ nsCString decodedHost;
+ idnService->ConvertACEtoUTF8 (host, decodedHost);
+
+ return ephy_permission_info_new (decodedHost.get(), type.get(), permission);
+}
diff --git a/embed/xulrunner/embed/EphySingle.h b/embed/xulrunner/embed/EphySingle.h
new file mode 100644
index 000000000..f30d7340a
--- /dev/null
+++ b/embed/xulrunner/embed/EphySingle.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2003 Christian Persch
+ * Copyright © 2003 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_SINGLE_H
+#define EPHY_SINGLE_H
+
+#include <nsCOMPtr.h>
+#include <nsIObserver.h>
+#include <nsIObserverService.h>
+
+#include "ephy-cookie-manager.h"
+#include "ephy-embed-single.h"
+#include "ephy-permission-manager.h"
+
+class nsICookie;
+class nsIPermission;
+
+class EphySingle : public nsIObserver
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVER
+
+ EphySingle();
+ virtual ~EphySingle();
+
+ nsresult Init (EphyEmbedSingle *aOwner);
+ nsresult Detach ();
+
+ PRBool IsOnline() { return mIsOnline; }
+
+protected:
+ nsresult EmitCookieNotification (const char *name, nsISupports *aSubject);
+ nsresult EmitPermissionNotification (const char *name, nsISupports *aSubject);
+ nsresult ExamineResponse (nsISupports *aSubject);
+ nsresult ExamineRequest (nsISupports *aSubject);
+ nsresult ExamineCookies (nsISupports *aSubject);
+
+private:
+ nsCOMPtr<nsIObserverService> mObserverService;
+ EphyEmbedSingle *mOwner;
+ PRBool mIsOnline;
+};
+
+EphyCookie *mozilla_cookie_to_ephy_cookie (nsICookie *cookie);
+
+EphyPermissionInfo *mozilla_permission_to_ephy_permission (nsIPermission *perm);
+
+#endif
diff --git a/embed/xulrunner/embed/EphyUtils.cpp b/embed/xulrunner/embed/EphyUtils.cpp
new file mode 100644
index 000000000..3f1b23687
--- /dev/null
+++ b/embed/xulrunner/embed/EphyUtils.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright © 2004 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <nsStringAPI.h>
+
+#include <gtkmozembed.h>
+#include <nsCOMPtr.h>
+#include <nsIDOMWindow.h>
+#include <nsIEmbeddingSiteWindow.h>
+#include <nsIFile.h>
+#include <nsIIOService.h>
+#include <nsIServiceManager.h>
+#include <nsIURI.h>
+#include <nsIWebBrowserChrome.h>
+#include <nsIWindowWatcher.h>
+#include <nsIXPConnect.h>
+#include <nsServiceManagerUtils.h>
+#include <nsXPCOM.h>
+
+#ifdef HAVE_GECKO_1_9
+#include <nsPIDOMWindow.h>
+#include <nsDOMJSUtils.h> /* for GetScriptContextFromJSContext */
+#include <nsIScriptContext.h>
+#include <nsIScriptGlobalObject.h>
+#endif
+
+#include "ephy-embed-shell.h"
+#include "ephy-embed-single.h"
+#include "ephy-file-helpers.h"
+
+#include "EphyUtils.h"
+
+nsresult
+EphyUtils::GetIOService (nsIIOService **ioService)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager (getter_AddRefs (mgr));
+ if (!mgr) return NS_ERROR_FAILURE;
+
+ rv = mgr->GetServiceByContractID ("@mozilla.org/network/io-service;1",
+ NS_GET_IID (nsIIOService),
+ (void **)ioService);
+ return rv;
+}
+
+nsresult
+EphyUtils::NewURI (nsIURI **result,
+ const nsAString &spec,
+ const char *charset,
+ nsIURI *baseURI)
+{
+ nsCString cSpec;
+ NS_UTF16ToCString (spec, NS_CSTRING_ENCODING_UTF8, cSpec);
+
+ return NewURI (result, cSpec, charset, baseURI);
+}
+
+nsresult
+EphyUtils::NewURI (nsIURI **result,
+ const nsACString &spec,
+ const char *charset,
+ nsIURI *baseURI)
+{
+ nsresult rv;
+ nsCOMPtr<nsIIOService> ioService;
+ rv = EphyUtils::GetIOService (getter_AddRefs (ioService));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ return ioService->NewURI (spec, charset, baseURI, result);
+}
+
+nsresult
+EphyUtils::NewFileURI (nsIURI **result,
+ nsIFile *spec)
+{
+ nsresult rv;
+ nsCOMPtr<nsIIOService> ioService;
+ rv = EphyUtils::GetIOService (getter_AddRefs (ioService));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ return ioService->NewFileURI (spec, result);
+}
+
+GtkWidget *
+EphyUtils::FindEmbed (nsIDOMWindow *aDOMWindow)
+{
+ if (!aDOMWindow) return nsnull;
+
+ nsCOMPtr<nsIWindowWatcher> wwatch
+ (do_GetService("@mozilla.org/embedcomp/window-watcher;1"));
+ NS_ENSURE_TRUE (wwatch, nsnull);
+
+ /* this DOM window may belong to some inner frame, we need
+ * to get the topmost DOM window to get the embed
+ */
+ nsCOMPtr<nsIDOMWindow> topWindow;
+ aDOMWindow->GetTop (getter_AddRefs (topWindow));
+ if (!topWindow) return nsnull;
+
+ nsCOMPtr<nsIWebBrowserChrome> windowChrome;
+ wwatch->GetChromeForWindow (topWindow, getter_AddRefs(windowChrome));
+ NS_ENSURE_TRUE (windowChrome, nsnull);
+
+ nsCOMPtr<nsIEmbeddingSiteWindow> window (do_QueryInterface(windowChrome));
+ NS_ENSURE_TRUE (window, nsnull);
+
+ nsresult rv;
+ GtkWidget *mozembed;
+ rv = window->GetSiteWindow ((void **)&mozembed);
+ NS_ENSURE_SUCCESS (rv, nsnull);
+
+ return mozembed;
+}
+
+GtkWidget *
+EphyUtils::FindGtkParent (nsIDOMWindow *aDOMWindow)
+{
+ GtkWidget *embed = FindEmbed (aDOMWindow);
+ if (!embed) return nsnull;
+
+ GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (embed));
+ if (!GTK_WIDGET_TOPLEVEL (toplevel)) return nsnull;
+
+ return toplevel;
+}
+
+char *
+EphyUtils::ConvertUTF16toUTF8 (const PRUnichar *aText,
+ PRInt32 aMaxLength)
+{
+ if (aText == nsnull) return NULL;
+
+ /* This depends on the assumption that
+ * typeof(PRUnichar) == typeof (gunichar2) == uint16,
+ * which should be pretty safe.
+ */
+ glong n_read = 0, n_written = 0;
+ char *converted = g_utf16_to_utf8 ((gunichar2*) aText, aMaxLength,
+ &n_read, &n_written, NULL);
+ /* FIXME loop from the end while !g_unichar_isspace (char)? */
+
+ return converted;
+}
+
+/* This isn't completely accurate: if you do window.prompt in one window, then
+ * call this in another window, it still returns TRUE ! Those are the wonders
+ * of recursive mainloops :-(
+ */
+PRBool
+EphyJSUtils::IsCalledFromScript ()
+{
+ nsresult rv;
+ nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
+ NS_ENSURE_SUCCESS (rv, PR_FALSE);
+
+ nsCOMPtr<nsIXPCNativeCallContext> ncc;
+ rv = xpc->GetCurrentNativeCallContext (getter_AddRefs (ncc));
+ NS_ENSURE_SUCCESS(rv, PR_FALSE);
+
+ return nsnull != ncc;
+}
+
+/* NOTE: Only call this when we're SURE that we're called directly from JS! */
+nsIDOMWindow *
+EphyJSUtils::GetDOMWindowFromCallContext ()
+{
+ /* TODO: We can do this on 1.8 too, but we'd need to use headers which include private string API
+ * so we'll have to move this to MozillaPrivate
+ */
+#ifdef HAVE_GECKO_1_9
+ nsresult rv;
+ nsCOMPtr<nsIXPConnect> xpc (do_GetService(nsIXPConnect::GetCID(), &rv));
+ NS_ENSURE_SUCCESS (rv, nsnull);
+
+ nsCOMPtr<nsIXPCNativeCallContext> ncc;
+ rv = xpc->GetCurrentNativeCallContext (getter_AddRefs (ncc));
+ NS_ENSURE_SUCCESS (rv, nsnull);
+
+ JSContext *cx = nsnull;
+ rv = ncc->GetJSContext(&cx);
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && cx, nsnull);
+
+ nsIScriptContext* scriptContext = GetScriptContextFromJSContext (cx);
+ if (!scriptContext) return nsnull;
+
+ nsIScriptGlobalObject *globalObject = scriptContext->GetGlobalObject();
+ if (!globalObject) return nsnull;
+
+ nsCOMPtr<nsPIDOMWindow> piWindow (do_QueryInterface (globalObject));
+ if (!piWindow) return nsnull;
+
+ return piWindow->GetOuterWindow ();
+#else
+ return nsnull;
+#endif
+}
diff --git a/embed/xulrunner/embed/EphyUtils.h b/embed/xulrunner/embed/EphyUtils.h
new file mode 100644
index 000000000..9d69fbb27
--- /dev/null
+++ b/embed/xulrunner/embed/EphyUtils.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2004 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_UTILS_H
+#define EPHY_UTILS_H
+
+// cannot include EphyUtils with internal strings!
+#ifdef MOZILLA_INTERNAL_API
+#error Cannot use EphyUtils with MOZILLA_INTERNAL_API
+#endif
+
+#include <nscore.h>
+
+#include <gtk/gtkwidget.h>
+
+class nsACString;
+class nsAString;
+class nsIDOMWindow;
+class nsIFile;
+class nsIIOService;
+class nsIURI;
+
+namespace EphyUtils
+{
+ nsresult GetIOService (nsIIOService **ioService);
+
+ nsresult NewURI (nsIURI **result,
+ const nsAString &spec,
+ const char *charset = nsnull,
+ nsIURI *baseURI = nsnull);
+
+ nsresult NewURI (nsIURI **result,
+ const nsACString &spec,
+ const char *charset = nsnull,
+ nsIURI *baseURI = nsnull);
+
+ nsresult NewFileURI (nsIURI **result,
+ nsIFile *spec);
+
+ GtkWidget *FindEmbed (nsIDOMWindow *aDOMWindow);
+
+ GtkWidget *FindGtkParent (nsIDOMWindow *aDOMWindow);
+
+ char * ConvertUTF16toUTF8 (const PRUnichar*, PRInt32);
+}
+
+namespace EphyJSUtils
+{
+ PRBool IsCalledFromScript ();
+
+ /* not addref'd! */ nsIDOMWindow* GetDOMWindowFromCallContext ();
+}
+
+#endif
diff --git a/embed/xulrunner/embed/EventContext.cpp b/embed/xulrunner/embed/EventContext.cpp
new file mode 100644
index 000000000..6e22fce8a
--- /dev/null
+++ b/embed/xulrunner/embed/EventContext.cpp
@@ -0,0 +1,1105 @@
+/*
+ * Copyright © 2000-2004 Marco Pesenti Gritti
+ * Copyright © 2003, 2004 Christian Persch
+ * Copyright © 2004 Crispin Flowerday
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <gdk/gdkkeysyms.h>
+
+#include <nsStringAPI.h>
+
+#include <nsComponentManagerUtils.h>
+#include <nsIDOM3Node.h>
+#include <nsIDOMAbstractView.h>
+#include <nsIDOMCharacterData.h>
+#include <nsIDOMCSSPrimitiveValue.h>
+#include <nsIDOMCSSStyleDeclaration.h>
+#include <nsIDOMDocument.h>
+#include <nsIDOMDocumentView.h>
+#include <nsIDOMElementCSSInlineStyle.h>
+#include <nsIDOMElement.h>
+#include <nsIDOMEvent.h>
+#include <nsIDOMEventTarget.h>
+#include <nsIDOMEventTarget.h>
+#include <nsIDOMHTMLAnchorElement.h>
+#include <nsIDOMHTMLAreaElement.h>
+#include <nsIDOMHTMLBodyElement.h>
+#include <nsIDOMHTMLButtonElement.h>
+#include <nsIDOMHTMLEmbedElement.h>
+#include <nsIDOMHTMLImageElement.h>
+#include <nsIDOMHTMLInputElement.h>
+#include <nsIDOMHTMLIsIndexElement.h>
+#include <nsIDOMHTMLLabelElement.h>
+#include <nsIDOMHTMLLegendElement.h>
+#include <nsIDOMHTMLMapElement.h>
+#include <nsIDOMHTMLObjectElement.h>
+#include <nsIDOMHTMLSelectElement.h>
+#include <nsIDOMHTMLTextAreaElement.h>
+#include <nsIDOMKeyEvent.h>
+#include <nsIDOMMouseEvent.h>
+#include <nsIDOMNode.h>
+#include <nsIDOMNodeList.h>
+#include <nsIDOMNSHTMLDocument.h>
+#include <nsIDOMNSUIEvent.h>
+#include <nsIInterfaceRequestor.h>
+#include <nsIInterfaceRequestorUtils.h>
+#include <nsIServiceManager.h>
+#include <nsIURI.h>
+
+#ifdef ALLOW_PRIVATE_API
+#include <nsIDOMNSEvent.h>
+#include <nsIDOMNSHTMLElement.h>
+#include <nsIDOMViewCSS.h>
+#include <nsIDOMViewCSS.h>
+#include <nsIDOMXULDocument.h>
+#include <nsITextToSubURI.h>
+#endif
+
+#include "ephy-debug.h"
+
+#include "EphyBrowser.h"
+#include "EphyUtils.h"
+
+#include "EventContext.h"
+
+
+#define KEY_CODE 256
+
+EventContext::EventContext ()
+{
+ LOG ("EventContext ctor [%p]", this);
+}
+
+EventContext::~EventContext ()
+{
+ LOG ("EventContext dtor [%p]", this);
+}
+
+nsresult EventContext::Init (EphyBrowser *browser)
+{
+ mBrowser = browser;
+ mDOMDocument = nsnull;
+
+ return NS_OK;
+}
+
+nsresult EventContext::GatherTextUnder (nsIDOMNode* aNode, nsAString& aResult)
+{
+ nsString text;
+ nsCOMPtr<nsIDOMNode> node;
+ aNode->GetFirstChild(getter_AddRefs(node));
+ PRUint32 depth = 1;
+
+ while (node && depth)
+ {
+ nsCOMPtr<nsIDOMCharacterData> charData(do_QueryInterface(node));
+ PRUint16 nodeType;
+
+ node->GetNodeType(&nodeType);
+ if (charData && nodeType == nsIDOMNode::TEXT_NODE)
+ {
+ /* Add this text to our collection. */
+ text += ' ';
+ nsString data;
+ charData->GetData(data);
+ text += data;
+ }
+ else
+ {
+ nsCOMPtr<nsIDOMHTMLImageElement> img(do_QueryInterface(node));
+ if (img)
+ {
+ nsString altText;
+ img->GetAlt(altText);
+ if (altText.Length())
+ {
+ text = altText;
+ break;
+ }
+ }
+ }
+
+ /* Find the next node to test. */
+ PRBool hasChildNodes;
+ node->HasChildNodes(&hasChildNodes);
+ if (hasChildNodes)
+ {
+ nsCOMPtr<nsIDOMNode> temp = node;
+ temp->GetFirstChild(getter_AddRefs(node));
+ depth++;
+ }
+ else
+ {
+ nsCOMPtr<nsIDOMNode> nextSibling;
+ node->GetNextSibling(getter_AddRefs(nextSibling));
+ if (nextSibling)
+ {
+ node = nextSibling;
+ }
+ else
+ {
+ nsCOMPtr<nsIDOMNode> parentNode;
+ node->GetParentNode(getter_AddRefs(parentNode));
+ if (!parentNode)
+ {
+ node = nsnull;
+ }
+ else
+ {
+ parentNode->GetNextSibling(getter_AddRefs(nextSibling));
+ node = nextSibling;
+ depth--;
+ }
+ }
+ }
+ }
+
+ /* FIXME we should trim spaces here */
+
+ aResult = text;
+
+ return NS_OK;
+}
+
+/* FIXME: we should resolve against the element's base, not the document's base */
+nsresult EventContext::ResolveBaseURL (const nsAString &relurl, nsACString &url)
+{
+ nsCString cRelURL;
+ NS_UTF16ToCString (relurl, NS_CSTRING_ENCODING_UTF8, cRelURL);
+
+ return mBaseURI->Resolve (cRelURL, url);
+}
+
+nsresult EventContext::Unescape (const nsACString &aEscaped, nsACString &aUnescaped)
+{
+ if (!aEscaped.Length()) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsITextToSubURI> escaper
+ (do_CreateInstance ("@mozilla.org/intl/texttosuburi;1"));
+ NS_ENSURE_TRUE (escaper, NS_ERROR_FAILURE);
+
+ nsresult rv;
+ nsCString encoding;
+ rv = mBrowser->GetEncoding (encoding);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ nsString unescaped;
+ rv = escaper->UnEscapeURIForUI (encoding, aEscaped, unescaped);
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && unescaped.Length(), NS_ERROR_FAILURE);
+
+ NS_UTF16ToCString (unescaped, NS_CSTRING_ENCODING_UTF8, aUnescaped);
+
+ return NS_OK;
+}
+
+nsresult EventContext::GetEventContext (nsIDOMEventTarget *EventTarget,
+ MozillaEmbedEvent *info)
+{
+ nsresult rv;
+
+ const PRUnichar hrefLiteral[] = {'h', 'r', 'e', 'f', '\0'};
+ const PRUnichar imgLiteral[] = {'i', 'm', 'g', '\0'};
+ const PRUnichar typeLiteral[] = {'t', 'y', 'p', 'e', '\0'};
+ const PRUnichar xlinknsLiteral[] = {'h', 't', 't', 'p', ':', '/', '/','w',
+ 'w', 'w', '.', 'w', '3', '.', 'o', 'r',
+ 'g', '/', '1', '9', '9', '9', '/', 'x',
+ 'l', 'i', 'n', 'k', '\0'};
+ const PRUnichar bodyLiteral[] = { 'b', 'o', 'd', 'y', '\0' };
+
+ mEmbedEvent = info;
+
+ info->context = EPHY_EMBED_CONTEXT_DOCUMENT;
+
+ nsCOMPtr<nsIDOMNode> node = do_QueryInterface(EventTarget, &rv);
+ if (NS_FAILED(rv) || !node) return NS_ERROR_FAILURE;
+
+ /* Is page xul ? then do not display context menus
+ * FIXME I guess there is an easier way ... */
+ /* From philipl: This test needs to be here otherwise we
+ * arrogantly assume we can QI to a HTMLElement, which is
+ * not true for xul content. */
+
+ nsCOMPtr<nsIDOMDocument> domDoc;
+ rv = node->GetOwnerDocument(getter_AddRefs(domDoc));
+ if (NS_FAILED(rv) || !domDoc) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIDOMXULDocument> xul_document = do_QueryInterface(domDoc);
+ if (xul_document)
+ {
+ info->context = EPHY_EMBED_CONTEXT_NONE;
+ return NS_ERROR_FAILURE;
+ }
+
+ mDOMDocument = domDoc;
+
+ rv = mBrowser->GetEncoding (mCharset);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ /* Get base URI and CSS view */
+ nsCOMPtr<nsIDOMDocumentView> docView (do_QueryInterface (domDoc));
+ NS_ENSURE_TRUE (docView, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDOMAbstractView> abstractView;
+ docView->GetDefaultView (getter_AddRefs (abstractView));
+ NS_ENSURE_TRUE (abstractView, NS_ERROR_FAILURE);
+ /* the abstract view is really the DOM window */
+
+ mViewCSS = do_QueryInterface (abstractView);
+ NS_ENSURE_TRUE (mViewCSS, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIWebNavigation> webNav (do_GetInterface (abstractView, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = webNav->GetCurrentURI (getter_AddRefs (mBaseURI));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ // Now we know that the page isn't a xul window, we can try and
+ // do something useful with it.
+
+ PRUint16 type;
+ rv = node->GetNodeType(&type);
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+ PRBool has_image = PR_FALSE;
+
+ nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(node);
+ if ((nsIDOMNode::ELEMENT_NODE == type) && element)
+ {
+ nsString uTag;
+ rv = element->GetLocalName(uTag);
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+ nsCString tag;
+ NS_UTF16ToCString (uTag, NS_CSTRING_ENCODING_UTF8, tag);
+
+ if (g_ascii_strcasecmp (tag.get(), "img") == 0)
+ {
+ nsString img;
+ nsCOMPtr <nsIDOMHTMLImageElement> image =
+ do_QueryInterface(node, &rv);
+ if (NS_FAILED(rv) || !image) return NS_ERROR_FAILURE;
+
+ rv = image->GetSrc (img);
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+ SetStringProperty ("image", img);
+ info->context |= EPHY_EMBED_CONTEXT_IMAGE;
+ has_image = PR_TRUE;
+ }
+ else if (g_ascii_strcasecmp (tag.get(), "area") == 0)
+ {
+ nsCOMPtr <nsIDOMHTMLAreaElement> area =
+ do_QueryInterface(node, &rv);
+ if (NS_FAILED(rv) || !area) return NS_ERROR_FAILURE;
+
+ // Parent node is the map itself
+ nsCOMPtr<nsIDOMNode> parentNode;
+ node->GetParentNode (getter_AddRefs(parentNode));
+
+ nsCOMPtr <nsIDOMHTMLMapElement> map =
+ do_QueryInterface(parentNode, &rv);
+ if (NS_FAILED(rv) || !area) return NS_ERROR_FAILURE;
+
+ nsString mapName;
+ rv = map->GetName (mapName);
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+ // Now we are searching for all the images with a usemap attribute
+ nsCOMPtr<nsIDOMNodeList> imgs;
+ rv = mDOMDocument->GetElementsByTagName (nsString(imgLiteral),
+ getter_AddRefs (imgs));
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+ PRUint32 imgs_count;
+ rv = imgs->GetLength (&imgs_count);
+ if (NS_FAILED (rv)) return NS_ERROR_FAILURE;
+
+ for (PRUint32 i = 0; i < imgs_count; i++)
+ {
+ nsCOMPtr<nsIDOMNode> aNode;
+ rv = imgs->Item (i, getter_AddRefs (aNode));
+ if (NS_FAILED (rv)) continue;
+
+ nsCOMPtr<nsIDOMHTMLImageElement> img =
+ do_QueryInterface(aNode, &rv);
+ if (NS_FAILED(rv) || !img) continue;
+
+ nsString imgMapName;
+ rv = img->GetUseMap (imgMapName);
+ if (NS_FAILED (rv)) continue;
+
+ // usemap always starts with #
+ imgMapName.Cut (0,1);
+
+ // Check if the current image is attached to the map we are looking for
+ if (imgMapName.Equals(mapName))
+ {
+ nsString imgSrc;
+ rv = img->GetSrc (imgSrc);
+ if (NS_FAILED(rv)) continue;
+
+ SetStringProperty ("image", imgSrc);
+ info->context |= EPHY_EMBED_CONTEXT_IMAGE;
+ has_image = PR_TRUE;
+
+ break;
+ }
+ }
+ }
+ else if (g_ascii_strcasecmp (tag.get(), "input") == 0)
+ {
+ CheckInput (node);
+ }
+ else if (g_ascii_strcasecmp (tag.get(), "textarea") == 0)
+ {
+ info->context |= EPHY_EMBED_CONTEXT_INPUT;
+ }
+ else if (g_ascii_strcasecmp (tag.get(), "object") == 0)
+ {
+ nsCOMPtr<nsIDOMHTMLObjectElement> object;
+ object = do_QueryInterface (node);
+ if (!element) return NS_ERROR_FAILURE;
+
+ nsString value;
+ object->GetType(value);
+
+ nsCString cValue;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cValue);
+
+ // MIME types are always lower case
+ if (g_str_has_prefix (cValue.get(), "image/"))
+ {
+ nsString img;
+
+ rv = object->GetData (img);
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+ nsCString cImg;
+ rv = ResolveBaseURL (img, cImg);
+ if (NS_FAILED (rv)) return NS_ERROR_FAILURE;
+
+ SetStringProperty ("image", cImg.get());
+ info->context |= EPHY_EMBED_CONTEXT_IMAGE;
+ has_image = PR_TRUE;
+ }
+ else
+ {
+ info->context = EPHY_EMBED_CONTEXT_NONE;
+ return NS_OK;
+ }
+ }
+ else if (g_ascii_strcasecmp (tag.get(), "html") == 0)
+ {
+ /* Clicked on part of the page without a <body>, so
+ * look for a background image in the body tag */
+ nsCOMPtr<nsIDOMNodeList> nodeList;
+
+ rv = mDOMDocument->GetElementsByTagName (nsString(bodyLiteral),
+ getter_AddRefs (nodeList));
+ if (NS_SUCCEEDED (rv) && nodeList)
+ {
+ nsCOMPtr<nsIDOMNode> bodyNode;
+ nodeList->Item (0, getter_AddRefs (bodyNode));
+
+ nsString cssurl;
+ rv = GetCSSBackground (bodyNode, cssurl);
+ if (NS_SUCCEEDED (rv))
+ {
+ nsCString bgimg;
+ rv = ResolveBaseURL (cssurl, bgimg);
+ if (NS_FAILED (rv))
+ return NS_ERROR_FAILURE;
+
+ SetStringProperty ("image", bgimg.get());
+ info->context |= EPHY_EMBED_CONTEXT_IMAGE;
+ has_image = PR_TRUE;
+ }
+ }
+ }
+ }
+
+ /* Is page framed ? */
+ PRBool framed;
+ IsPageFramed (node, &framed);
+ SetIntProperty ("framed_page", framed);
+
+ /* Bubble out, looking for items of interest */
+ while (node)
+ {
+ nsCOMPtr <nsIDOMElement> dom_elem = do_QueryInterface(node);
+ if (dom_elem)
+ {
+ nsString value;
+ dom_elem->GetAttributeNS (nsString(xlinknsLiteral),
+ nsString(typeLiteral), value);
+
+ nsCString cValue;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cValue);
+
+ if (g_ascii_strcasecmp (cValue.get(), "simple") == 0)
+ {
+ info->context |= EPHY_EMBED_CONTEXT_LINK;
+ dom_elem->GetAttributeNS (nsString(xlinknsLiteral),
+ nsString(hrefLiteral), value);
+
+ SetURIProperty (node, "link", value);
+ CheckLinkScheme (value);
+ }
+ }
+
+ rv = node->GetNodeType(&type);
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+ element = do_QueryInterface(node);
+ if ((nsIDOMNode::ELEMENT_NODE == type) && element)
+ {
+ nsString uTag;
+ rv = element->GetLocalName(uTag);
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+ nsCString tag;
+ NS_UTF16ToCString (uTag, NS_CSTRING_ENCODING_UTF8, tag);
+
+ /* Link */
+ if (g_ascii_strcasecmp (tag.get(), "a") == 0)
+ {
+ nsString tmp;
+
+ rv = GatherTextUnder (node, tmp);
+ if (NS_SUCCEEDED(rv))
+ SetStringProperty ("linktext", tmp);
+
+ nsCOMPtr <nsIDOMHTMLAnchorElement> anchor =
+ do_QueryInterface(node);
+
+ nsCString href;
+ anchor->GetHref (tmp);
+ NS_UTF16ToCString (tmp, NS_CSTRING_ENCODING_UTF8, href);
+
+ if (g_str_has_prefix (href.get(), "mailto:"))
+ {
+ /* cut "mailto:" */
+ href.Cut (0, 7);
+
+ char *str = g_strdup (href.get());
+ g_strdelimit (str, "?", '\0');
+
+ nsCString unescapedHref;
+ rv = Unescape (nsCString(str), unescapedHref);
+ if (NS_SUCCEEDED (rv) && unescapedHref.Length())
+ {
+ SetStringProperty ("email", unescapedHref.get());
+ info->context |= EPHY_EMBED_CONTEXT_EMAIL_LINK;
+ }
+ g_free (str);
+ }
+
+ if (anchor && tmp.Length())
+ {
+ info->context |= EPHY_EMBED_CONTEXT_LINK;
+
+ SetURIProperty (node, "link", tmp);
+ CheckLinkScheme (tmp);
+ rv = anchor->GetHreflang (tmp);
+ if (NS_SUCCEEDED(rv))
+ SetStringProperty ("link_lang", tmp);
+ rv = anchor->GetTarget (tmp);
+ if (NS_SUCCEEDED(rv))
+ SetStringProperty ("link_target", tmp);
+ rv = anchor->GetRel (tmp);
+ if (NS_SUCCEEDED(rv))
+ SetStringProperty ("link_rel", tmp);
+ rv = anchor->GetRev (tmp);
+ if (NS_SUCCEEDED(rv))
+ SetStringProperty ("link_rev", tmp);
+ rv = element->GetTitle (tmp);
+ if (NS_SUCCEEDED(rv))
+ SetStringProperty ("link_title", tmp);
+ rv = anchor->GetType (tmp);
+ if (NS_SUCCEEDED(rv))
+ SetStringProperty ("link_type", tmp);
+
+ nsCString linkType;
+ NS_UTF16ToCString (tmp, NS_CSTRING_ENCODING_UTF8, linkType);
+
+ if (g_ascii_strcasecmp (linkType.get(), "text/smartbookmark") == 0)
+ {
+ SetIntProperty ("link_is_smart", TRUE);
+
+ nsCOMPtr<nsIDOMNode> childNode;
+ node->GetFirstChild (getter_AddRefs(childNode));
+ if (childNode)
+ {
+ nsCOMPtr <nsIDOMHTMLImageElement> image =
+ do_QueryInterface(childNode, &rv);
+
+ if (image)
+ {
+ nsString img;
+ rv = image->GetSrc (img);
+ if (!NS_FAILED(rv))
+ {
+ SetStringProperty ("image", img);
+ }
+ }
+ }
+ }
+ else
+ {
+ SetIntProperty ("link_is_smart", FALSE);
+ }
+ }
+
+ }
+ else if (g_ascii_strcasecmp (tag.get(), "option") == 0)
+ {
+ info->context = EPHY_EMBED_CONTEXT_NONE;
+ return NS_OK;
+ }
+ else if (g_ascii_strcasecmp (tag.get(), "area") == 0)
+ {
+ info->context |= EPHY_EMBED_CONTEXT_LINK;
+ nsCOMPtr <nsIDOMHTMLAreaElement> area =
+ do_QueryInterface(node, &rv);
+ if (NS_SUCCEEDED(rv) && area)
+ {
+ nsString href;
+ rv = area->GetHref (href);
+ if (NS_FAILED(rv))
+ return NS_ERROR_FAILURE;
+
+ SetURIProperty (node, "link", href);
+ CheckLinkScheme (href);
+ }
+ }
+ else if (g_ascii_strcasecmp (tag.get(), "input") == 0)
+ {
+ CheckInput (node);
+ }
+ else if (g_ascii_strcasecmp (tag.get(), "textarea") == 0)
+ {
+ info->context |= EPHY_EMBED_CONTEXT_INPUT;
+ }
+
+ if (!has_image)
+ {
+ nsString cssurl;
+ rv = GetCSSBackground (node, cssurl);
+ if (NS_SUCCEEDED (rv))
+ {
+ nsCString bgimg;
+
+ rv = ResolveBaseURL (cssurl, bgimg);
+ if (NS_FAILED (rv))
+ return NS_ERROR_FAILURE;
+ SetStringProperty ("image", bgimg.get());
+ info->context |= EPHY_EMBED_CONTEXT_IMAGE;
+ has_image = PR_TRUE;
+ }
+ }
+ }
+
+ nsCOMPtr<nsIDOMNode> parentNode;
+ node->GetParentNode (getter_AddRefs(parentNode));
+ node = parentNode;
+ }
+
+ return NS_OK;
+}
+
+nsresult EventContext::GetCSSBackground (nsIDOMNode *node, nsAString& url)
+{
+ if (!mViewCSS) return NS_ERROR_NOT_INITIALIZED;
+
+ nsresult rv;
+
+ const PRUnichar bgimage[] = {'b', 'a', 'c', 'k', 'g', 'r', 'o', 'u', 'n', 'd',
+ '-', 'i', 'm', 'a', 'g', 'e', '\0'};
+
+ nsCOMPtr<nsIDOMElement> element = do_QueryInterface (node);
+ NS_ENSURE_TRUE (element, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDOMCSSStyleDeclaration> decl;
+ mViewCSS->GetComputedStyle (element, nsString(),
+ getter_AddRefs (decl));
+ NS_ENSURE_TRUE (decl, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDOMCSSValue> CSSValue;
+ decl->GetPropertyCSSValue (nsString(bgimage),
+ getter_AddRefs (CSSValue));
+
+ nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue =
+ do_QueryInterface (CSSValue);
+ if (!primitiveValue) return NS_ERROR_FAILURE;
+
+ PRUint16 type;
+ rv = primitiveValue->GetPrimitiveType (&type);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ if (type != nsIDOMCSSPrimitiveValue::CSS_URI) return NS_ERROR_FAILURE;
+
+ rv = primitiveValue->GetStringValue (url);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ return NS_OK;
+}
+
+nsresult EventContext::GetTargetCoords (nsIDOMEventTarget *aTarget, PRInt32 *aX, PRInt32 *aY)
+{
+ /* Calculate the node coordinates relative to the widget origin */
+ nsCOMPtr<nsIDOMNSHTMLElement> elem (do_QueryInterface(aTarget));
+
+ PRInt32 x = 0, y = 0;
+ while (elem)
+ {
+ PRInt32 val;
+ elem->GetOffsetTop(&val); y += val;
+ elem->GetScrollTop(&val); y -= val;
+ elem->GetOffsetLeft(&val); x += val;
+ elem->GetScrollLeft(&val); x -= val;
+
+ nsCOMPtr<nsIDOMElement> parent;
+ elem->GetOffsetParent (getter_AddRefs (parent));
+ elem = do_QueryInterface(parent);
+ }
+
+ *aX = x;
+ *aY = y;
+
+ return NS_OK;
+}
+
+nsresult EventContext::GetMouseEventInfo (nsIDOMMouseEvent *aMouseEvent, MozillaEmbedEvent *info)
+{
+ /* FIXME: casting 32-bit guint* to PRUint16* below will break on big-endian */
+ PRUint16 btn = 1729;
+ aMouseEvent->GetButton (&btn);
+
+ switch (btn)
+ {
+ /* mozilla's button counting is one-off from gtk+'s */
+ case 0:
+ info->button = 1;
+ break;
+ case 1:
+ info->button = 2;
+ break;
+ case 2:
+ info->button = 3;
+ break;
+
+ case (PRUint16) -1:
+ /* when the user submits a form with Return, mozilla synthesises
+ * a _mouse_ click event with btn=65535 (-1).
+ */
+ default:
+ info->button = 0;
+ break;
+ }
+
+ if (info->button != 0)
+ {
+ /* OTOH, casting only between (un)signedness is safe */
+ aMouseEvent->GetScreenX ((PRInt32*)&info->x);
+ aMouseEvent->GetScreenY ((PRInt32*)&info->y);
+ }
+ else /* this is really a keyboard event */
+ {
+ nsCOMPtr<nsIDOMEventTarget> eventTarget;
+ aMouseEvent->GetTarget (getter_AddRefs (eventTarget));
+
+ GetTargetCoords (eventTarget, (PRInt32*)&info->x, (PRInt32*)&info->y);
+ }
+
+ /* be sure we are not clicking on the scroolbars */
+
+ nsCOMPtr<nsIDOMNSEvent> nsEvent = do_QueryInterface(aMouseEvent);
+ if (!nsEvent) return NS_ERROR_FAILURE;
+
+#ifdef MOZ_NSIDOMNSEVENT_GETISTRUSTED
+ /* make sure the event is trusted */
+ PRBool isTrusted = PR_FALSE;
+ nsEvent->GetIsTrusted (&isTrusted);
+ if (!isTrusted) return NS_ERROR_UNEXPECTED;
+#endif /* MOZ_NSIDOMNSEVENT_GETISTRUSTED */
+
+ nsresult rv;
+ nsCOMPtr<nsIDOMEventTarget> OriginalTarget;
+ rv = nsEvent->GetOriginalTarget(getter_AddRefs(OriginalTarget));
+ if (NS_FAILED (rv) || !OriginalTarget) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIDOMNode> OriginalNode = do_QueryInterface(OriginalTarget);
+ if (!OriginalNode) return NS_ERROR_FAILURE;
+
+ nsString nodename;
+ OriginalNode->GetNodeName(nodename);
+ nsCString cNodeName;
+ NS_UTF16ToCString (nodename, NS_CSTRING_ENCODING_UTF8, cNodeName);
+
+ if (g_ascii_strcasecmp (cNodeName.get(), "xul:scrollbarbutton") == 0 ||
+ g_ascii_strcasecmp (cNodeName.get(), "xul:thumb") == 0 ||
+ g_ascii_strcasecmp (cNodeName.get(), "xul:vbox") == 0 ||
+ g_ascii_strcasecmp (cNodeName.get(), "xul:spacer") == 0 ||
+ g_ascii_strcasecmp (cNodeName.get(), "xul:slider") == 0)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIDOMEventTarget> EventTarget;
+ rv = aMouseEvent->GetTarget(getter_AddRefs(EventTarget));
+ if (NS_FAILED (rv) || !EventTarget) return NS_ERROR_FAILURE;
+
+ rv = GetEventContext (EventTarget, info);
+ if (NS_FAILED (rv)) return rv;
+
+ /* Get the modifier */
+
+ PRBool mod_key;
+
+ info->modifier = 0;
+
+ aMouseEvent->GetAltKey(&mod_key);
+ if (mod_key) info->modifier |= GDK_MOD1_MASK;
+
+ aMouseEvent->GetShiftKey(&mod_key);
+ if (mod_key) info->modifier |= GDK_SHIFT_MASK;
+
+ /* no need to check GetMetaKey, it's always PR_FALSE,
+ * see widget/src/gtk2/nsWindow.cpp:InitMouseEvent
+ */
+
+ aMouseEvent->GetCtrlKey(&mod_key);
+ if (mod_key) info->modifier |= GDK_CONTROL_MASK;
+
+ return NS_OK;
+}
+
+nsresult EventContext::GetKeyEventInfo (nsIDOMKeyEvent *aKeyEvent, MozillaEmbedEvent *info)
+{
+#ifdef MOZ_NSIDOMNSEVENT_GETISTRUSTED
+ /* make sure the event is trusted */
+ nsCOMPtr<nsIDOMNSEvent> nsEvent (do_QueryInterface (aKeyEvent));
+ NS_ENSURE_TRUE (nsEvent, NS_ERROR_FAILURE);
+
+ PRBool isTrusted = PR_FALSE;
+ nsEvent->GetIsTrusted (&isTrusted);
+ if (!isTrusted) return NS_ERROR_UNEXPECTED;
+#endif /* MOZ_NSIDOMNSEVENT_GETISTRUSTED */
+
+
+ info->button = 0;
+
+ nsresult rv;
+ PRUint32 keyCode;
+ rv = aKeyEvent->GetKeyCode(&keyCode);
+ if (NS_FAILED(rv)) return rv;
+ info->keycode = keyCode;
+
+ nsCOMPtr<nsIDOMEventTarget> target;
+ rv = aKeyEvent->GetTarget(getter_AddRefs(target));
+ if (NS_FAILED(rv) || !target) return NS_ERROR_FAILURE;
+
+ GetTargetCoords (target, (PRInt32*)&info->x, (PRInt32*)&info->y);
+
+ /* Context */
+ rv = GetEventContext (target, info);
+ if (NS_FAILED(rv)) return rv;
+
+ /* Get the modifier */
+
+ PRBool mod_key;
+
+ info->modifier = 0;
+
+ aKeyEvent->GetAltKey(&mod_key);
+ if (mod_key) info->modifier |= GDK_MOD1_MASK;
+
+ aKeyEvent->GetShiftKey(&mod_key);
+ if (mod_key) info->modifier |= GDK_SHIFT_MASK;
+
+ aKeyEvent->GetMetaKey(&mod_key);
+ if (mod_key) info->modifier |= GDK_MOD2_MASK;
+
+ aKeyEvent->GetCtrlKey(&mod_key);
+ if (mod_key) info->modifier |= GDK_CONTROL_MASK;
+
+ return NS_OK;
+}
+
+nsresult EventContext::IsPageFramed (nsIDOMNode *node, PRBool *Framed)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIDOMDocument> mainDocument;
+ rv = mBrowser->GetDocument (getter_AddRefs(mainDocument));
+ if (NS_FAILED (rv) || !mainDocument) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIDOMDocument> nodeDocument;
+ rv = node->GetOwnerDocument (getter_AddRefs(nodeDocument));
+ if (NS_FAILED (rv) || !nodeDocument) return NS_ERROR_FAILURE;
+
+ *Framed = (mainDocument != nodeDocument);
+
+ return NS_OK;
+}
+
+nsresult EventContext::GetTargetDocument (nsIDOMDocument **domDoc)
+{
+ if (!mDOMDocument) return NS_ERROR_FAILURE;
+
+ *domDoc = mDOMDocument.get();
+
+ NS_IF_ADDREF(*domDoc);
+
+ return NS_OK;
+}
+
+nsresult EventContext::CheckInput (nsIDOMNode *aNode)
+{
+ const PRUnichar typeLiteral[] = { 't', 'y', 'p', 'e', '\0' };
+
+ nsCOMPtr<nsIDOMElement> element;
+ element = do_QueryInterface (aNode);
+ if (!element) return NS_ERROR_FAILURE;
+
+ nsString uValue;
+ element->GetAttribute (nsString(typeLiteral), uValue);
+
+ nsCString value;
+ NS_UTF16ToCString (uValue, NS_CSTRING_ENCODING_UTF8, value);
+
+ if (g_ascii_strcasecmp (value.get(), "image") == 0)
+ {
+ mEmbedEvent->context |= EPHY_EMBED_CONTEXT_IMAGE;
+ nsCOMPtr<nsIDOMHTMLInputElement> input;
+ input = do_QueryInterface (aNode);
+ if (!input) return NS_ERROR_FAILURE;
+
+ nsresult rv;
+ nsString img;
+ rv = input->GetSrc (img);
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+ nsCString cImg;
+ rv = ResolveBaseURL (img, cImg);
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+ SetStringProperty ("image", cImg.get());
+ }
+ else if (g_ascii_strcasecmp (value.get(), "radio") != 0 &&
+ g_ascii_strcasecmp (value.get(), "submit") != 0 &&
+ g_ascii_strcasecmp (value.get(), "reset") != 0 &&
+ g_ascii_strcasecmp (value.get(), "hidden") != 0 &&
+ g_ascii_strcasecmp (value.get(), "button") != 0 &&
+ g_ascii_strcasecmp (value.get(), "checkbox") != 0)
+ {
+ mEmbedEvent->context |= EPHY_EMBED_CONTEXT_INPUT;
+
+ if (g_ascii_strcasecmp (value.get(), "password") == 0)
+ {
+ mEmbedEvent->context |= EPHY_EMBED_CONTEXT_INPUT_PASSWORD;
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult EventContext::CheckLinkScheme (const nsAString &link)
+{
+ nsCOMPtr<nsIURI> uri;
+ EphyUtils::NewURI (getter_AddRefs (uri), link);
+ if (!uri) return NS_ERROR_FAILURE;
+
+ nsresult rv;
+ nsCString scheme;
+ rv = uri->GetScheme (scheme);
+ if (NS_FAILED (rv)) return NS_ERROR_FAILURE;
+
+ if (g_ascii_strcasecmp (scheme.get(), "http") == 0 ||
+ g_ascii_strcasecmp (scheme.get(), "https") == 0 ||
+ g_ascii_strcasecmp (scheme.get(), "ftp") == 0 ||
+ g_ascii_strcasecmp (scheme.get(), "file") == 0 ||
+ g_ascii_strcasecmp (scheme.get(), "smb") == 0 ||
+ g_ascii_strcasecmp (scheme.get(), "sftp") == 0 ||
+ g_ascii_strcasecmp (scheme.get(), "ssh") == 0 ||
+ g_ascii_strcasecmp (scheme.get(), "data") == 0 ||
+ g_ascii_strcasecmp (scheme.get(), "resource") == 0 ||
+ g_ascii_strcasecmp (scheme.get(), "about") == 0 ||
+ g_ascii_strcasecmp (scheme.get(), "gopher") == 0)
+ {
+ SetIntProperty ("link-has-web-scheme", TRUE);
+ }
+
+ return NS_OK;
+}
+
+nsresult EventContext::SetIntProperty (const char *name, int value)
+{
+
+ GValue *val = g_new0 (GValue, 1);
+
+ g_value_init (val, G_TYPE_INT);
+
+ g_value_set_int (val, value);
+
+ mozilla_embed_event_set_property (mEmbedEvent, name, val);
+
+ return NS_OK;
+}
+
+nsresult EventContext::SetStringProperty (const char *name, const char *value)
+{
+ GValue *val = g_new0 (GValue, 1);
+
+ g_value_init (val, G_TYPE_STRING);
+
+ g_value_set_string (val, value);
+
+ mozilla_embed_event_set_property (mEmbedEvent, name, val);
+
+ return NS_OK;
+}
+
+nsresult EventContext::SetStringProperty (const char *name, const nsAString &value)
+{
+ nsCString cValue;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cValue);
+ return SetStringProperty (name, cValue.get());
+}
+
+nsresult EventContext::SetURIProperty (nsIDOMNode *node, const char *name, const nsACString &value)
+{
+ nsresult rv;
+ nsCOMPtr<nsIURI> uri;
+ rv = EphyUtils::NewURI (getter_AddRefs (uri), value, mCharset.Length () ? mCharset.get() : nsnull, mBaseURI);
+ if (NS_SUCCEEDED (rv) && uri)
+ {
+ /* Hide password part */
+ nsCString user;
+ uri->GetUsername (user);
+ uri->SetUserPass (user);
+
+ nsCString spec;
+ uri->GetSpec (spec);
+ rv = SetStringProperty (name, spec.get());
+ }
+ else
+ {
+ rv = SetStringProperty (name, nsCString(value).get());
+ }
+
+ return rv;
+}
+
+nsresult EventContext::SetURIProperty (nsIDOMNode *node, const char *name, const nsAString &value)
+{
+ nsCString cValue;
+ NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cValue);
+ return SetURIProperty (node, name, cValue);
+}
+
+/* static */
+PRBool
+EventContext::CheckKeyPress (nsIDOMKeyEvent *aEvent)
+{
+ PRBool retval = PR_FALSE;
+
+ /* make sure the event is trusted */
+ nsCOMPtr<nsIDOMNSEvent> nsEvent (do_QueryInterface (aEvent));
+ NS_ENSURE_TRUE (nsEvent, retval);
+ PRBool isTrusted = PR_FALSE;
+ nsEvent->GetIsTrusted (&isTrusted);
+ if (!isTrusted) return retval;
+
+ /* check for alt/ctrl */
+ PRBool isCtrl = PR_FALSE, isAlt = PR_FALSE;
+ aEvent->GetCtrlKey (&isCtrl);
+ aEvent->GetAltKey (&isAlt);
+ if (isCtrl || isAlt) return retval;
+
+ nsCOMPtr<nsIDOMNSUIEvent> uiEvent (do_QueryInterface (aEvent));
+ NS_ENSURE_TRUE (uiEvent, retval);
+
+ /* check for already handled event */
+ PRBool isPrevented = PR_FALSE;
+ uiEvent->GetPreventDefault (&isPrevented);
+ if (isPrevented) return retval;
+
+ /* check for form controls */
+ nsresult rv;
+ nsCOMPtr<nsIDOMEventTarget> target;
+ rv = aEvent->GetTarget (getter_AddRefs (target));
+ NS_ENSURE_SUCCESS (rv, retval);
+
+ nsCOMPtr<nsIDOMHTMLInputElement> inputElement (do_QueryInterface (target));
+ if (inputElement)
+ {
+ nsString type;
+ inputElement->GetType (type);
+
+ nsCString (cType);
+ NS_UTF16ToCString (type, NS_CSTRING_ENCODING_UTF8, cType);
+
+ if (g_ascii_strcasecmp (cType.get(), "text") == 0 ||
+ g_ascii_strcasecmp (cType.get(), "password") == 0 ||
+ g_ascii_strcasecmp (cType.get(), "file") == 0) return retval;
+ }
+
+ nsCOMPtr<nsIDOMHTMLTextAreaElement> textArea;
+ nsCOMPtr<nsIDOMHTMLSelectElement> selectElement;
+ nsCOMPtr<nsIDOMHTMLIsIndexElement> indexElement;
+ nsCOMPtr<nsIDOMHTMLObjectElement> objectElement;
+ nsCOMPtr<nsIDOMHTMLEmbedElement> embedElement;
+
+ if ((textArea = do_QueryInterface (target)) ||
+ (selectElement = do_QueryInterface (target)) ||
+ (indexElement = do_QueryInterface (target)) ||
+ (objectElement = do_QueryInterface (target)) ||
+ (embedElement = do_QueryInterface (target))) return retval;
+
+ /* check for design mode */
+ nsCOMPtr<nsIDOMNode> node (do_QueryInterface (target, &rv));
+ NS_ENSURE_SUCCESS (rv, PR_FALSE);
+
+ nsCOMPtr<nsIDOMDocument> doc;
+ rv = node->GetOwnerDocument (getter_AddRefs (doc));
+ NS_ENSURE_SUCCESS (rv, retval);
+
+ nsCOMPtr<nsIDOMXULDocument> xul_document (do_QueryInterface(doc, &rv));
+ if (xul_document) return retval;
+
+ nsCOMPtr<nsIDOMNSHTMLDocument> htmlDoc (do_QueryInterface (doc));
+ if (htmlDoc)
+ {
+ nsString uDesign;
+ rv = htmlDoc->GetDesignMode (uDesign);
+ NS_ENSURE_SUCCESS (rv, retval);
+
+ nsCString design;
+ NS_UTF16ToCString (uDesign, NS_CSTRING_ENCODING_UTF8, design);
+
+ retval = g_ascii_strcasecmp (design.get(), "on") != 0;
+ }
+ else
+ {
+ retval = PR_TRUE;
+ }
+
+ return retval;
+}
diff --git a/embed/xulrunner/embed/EventContext.h b/embed/xulrunner/embed/EventContext.h
new file mode 100644
index 000000000..ddffcf1fc
--- /dev/null
+++ b/embed/xulrunner/embed/EventContext.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright © 2000-2004 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EVENT_CONTEXT_H
+#define EVENT_CONTEXT_H
+
+#include "ephy-embed.h"
+#include "mozilla-embed-event.h"
+
+class EphyBrowser;
+class nsIDOMDocument;
+class nsIDOMEvent;
+class nsIDOMEventTarget;
+class nsIDOMHTMLAnchorElement;
+class nsIDOMHTMLAreaElement;
+class nsIDOMHTMLBodyElement;
+class nsIDOMKeyEvent;
+class nsIDOMMouseEvent;
+class nsIDOMNode;
+class nsIDOMViewCSS;
+class nsIURI;
+
+class EventContext
+{
+public:
+ EventContext();
+ ~EventContext();
+
+ nsresult Init (EphyBrowser *wrapper);
+ nsresult GetMouseEventInfo (nsIDOMMouseEvent *event, MozillaEmbedEvent *info);
+ nsresult GetKeyEventInfo (nsIDOMKeyEvent *event, MozillaEmbedEvent *info);
+ nsresult GetTargetDocument (nsIDOMDocument **domDoc);
+
+ static PRBool CheckKeyPress (nsIDOMKeyEvent *aEvent);
+
+private:
+ EphyBrowser *mBrowser;
+ MozillaEmbedEvent *mEmbedEvent;
+ nsCOMPtr<nsIDOMDocument> mDOMDocument;
+ nsCOMPtr<nsIDOMViewCSS> mViewCSS;
+ nsCOMPtr<nsIURI> mBaseURI;
+ nsCString mCharset;
+
+ nsresult GetTargetCoords (nsIDOMEventTarget *aTarget, PRInt32 *aX, PRInt32 *aY);
+ nsresult GatherTextUnder (nsIDOMNode* aNode, nsAString& aResult);
+ nsresult ResolveBaseURL (const nsAString &relurl, nsACString &url);
+ nsresult Unescape (const nsACString &aEscaped, nsACString &aUnescaped);
+ nsresult GetEventContext (nsIDOMEventTarget *EventTarget,
+ MozillaEmbedEvent *info);
+ nsresult GetCSSBackground (nsIDOMNode *node, nsAString& url);
+ nsresult IsPageFramed (nsIDOMNode *node, PRBool *Framed);
+ nsresult CheckInput (nsIDOMNode *node);
+ nsresult CheckLinkScheme (const nsAString &link);
+ nsresult SetIntProperty (const char *name, int value);
+ nsresult SetStringProperty (const char *name, const char *value);
+ nsresult SetStringProperty (const char *name, const nsAString &value);
+ nsresult SetURIProperty (nsIDOMNode *node, const char *name, const nsAString &value);
+ nsresult SetURIProperty (nsIDOMNode *node, const char *name, const nsACString &value);
+};
+
+#endif
diff --git a/embed/xulrunner/embed/FilePicker.cpp b/embed/xulrunner/embed/FilePicker.cpp
new file mode 100644
index 000000000..78cc8f50d
--- /dev/null
+++ b/embed/xulrunner/embed/FilePicker.cpp
@@ -0,0 +1,492 @@
+/*
+ * Copyright © 2001 Philip Langdale
+ * Copyright © 2003, 2004 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib/gconvert.h>
+#include <glib/gi18n.h>
+#include <gtk/gtkfilefilter.h>
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkstock.h>
+
+#include <nsStringAPI.h>
+
+#include <nsCOMPtr.h>
+#include <nsIDOMWindow.h>
+#include <nsIFileURL.h>
+#include <nsILocalFile.h>
+#include <nsIPromptService.h>
+#include <nsIServiceManager.h>
+#include <nsIURI.h>
+#include <nsNetCID.h>
+
+#include "ephy-debug.h"
+#include "ephy-gui.h"
+#include "ephy-prefs.h"
+
+#include "AutoJSContextStack.h"
+#include "AutoWindowModalState.h"
+#include "EphyUtils.h"
+
+#include "FilePicker.h"
+
+NS_IMPL_ISUPPORTS1(GFilePicker, nsIFilePicker)
+
+GFilePicker::GFilePicker()
+: mDialog(nsnull)
+, mMode(nsIFilePicker::modeOpen)
+{
+ LOG ("GFilePicker ctor (%p)", this);
+}
+
+GFilePicker::~GFilePicker()
+{
+ LOG ("GFilePicker dtor (%p)", this);
+
+ if (mDialog)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (mDialog), (gpointer *) &mDialog);
+ gtk_widget_destroy (GTK_WIDGET (mDialog));
+ }
+}
+
+/* void init (in nsIDOMWindow parent, in AString title, in short mode); */
+#ifdef MOZ_NSIFILEPICKER_NSASTRING_
+NS_IMETHODIMP GFilePicker::Init(nsIDOMWindow *parent, const nsAString& title, PRInt16 mode)
+#else
+NS_IMETHODIMP GFilePicker::Init(nsIDOMWindowInternal *parent, const PRUnichar *title, PRInt16 mode)
+#endif
+{
+ LOG ("GFilePicker::Init");
+
+ mParent = do_QueryInterface (parent);
+
+ GtkWidget *gtkparent = EphyUtils::FindGtkParent (parent);
+#if defined(MOZ_NSIFILEPICKER_NSASTRING_)
+ NS_ENSURE_TRUE (gtkparent, NS_ERROR_FAILURE);
+#endif
+
+ nsCString cTitle;
+#ifdef MOZ_NSIFILEPICKER_NSASTRING_
+ NS_UTF16ToCString (title, NS_CSTRING_ENCODING_UTF8, cTitle);
+#else
+ NS_UTF16ToCString (nsString(title), NS_CSTRING_ENCODING_UTF8, cTitle);
+#endif
+
+ mMode = mode;
+
+ GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
+ switch (mode)
+ {
+ case nsIFilePicker::modeGetFolder:
+ action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
+ break;
+ case nsIFilePicker::modeOpenMultiple:
+ case nsIFilePicker::modeOpen:
+ action = GTK_FILE_CHOOSER_ACTION_OPEN;
+ break;
+ case nsIFilePicker::modeSave:
+ action = GTK_FILE_CHOOSER_ACTION_SAVE;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ mDialog = ephy_file_chooser_new (cTitle.get(), gtkparent, action,
+ CONF_STATE_UPLOAD_DIR,
+ EPHY_FILE_FILTER_NONE);
+
+ if (parent)
+ {
+ gtk_window_group_add_window (ephy_gui_ensure_window_group (GTK_WINDOW (gtkparent)),
+ GTK_WINDOW (mDialog));
+ }
+
+ if (mode == nsIFilePicker::modeOpenMultiple)
+ {
+ gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (mDialog), TRUE);
+ }
+ if (mMode == nsIFilePicker::modeSave)
+ {
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (mDialog), TRUE);
+ }
+
+ g_object_add_weak_pointer (G_OBJECT (mDialog), (gpointer *) &mDialog);
+
+ return NS_OK;
+}
+
+/* void appendFilters (in long filterMask); */
+NS_IMETHODIMP GFilePicker::AppendFilters(PRInt32 filterMask)
+{
+ NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);
+
+ LOG ("GFilePicker::AppendFilters mask=%d", filterMask);
+
+ // http://lxr.mozilla.org/seamonkey/source/xpfe/components/filepicker/res/locale/en-US/filepicker.properties
+ // http://lxr.mozilla.org/seamonkey/source/xpfe/components/filepicker/src/nsFilePicker.js line 131 ff
+
+ if (filterMask & nsIFilePicker::filterAll)
+ {
+ ephy_file_chooser_add_pattern_filter (mDialog, _("All files"),
+ "*", (char*) NULL);
+ }
+ if (filterMask & nsIFilePicker::filterHTML)
+ {
+ ephy_file_chooser_add_mime_filter (mDialog, _("Web pages"),
+ "text/html",
+ "application/xhtml+xml",
+ "text/xml",
+ (char *) NULL);
+ }
+ if (filterMask & nsIFilePicker::filterText)
+ {
+ ephy_file_chooser_add_pattern_filter (mDialog, _("Text files"),
+ "*.txt", "*.text", NULL);
+ }
+ if (filterMask & nsIFilePicker::filterImages)
+ {
+ ephy_file_chooser_add_mime_filter (mDialog, _("Images"),
+ "image/png",
+ "image/jpeg",
+ "image/gif",
+ (char *) NULL);
+ }
+ if (filterMask & nsIFilePicker::filterXML)
+ {
+ ephy_file_chooser_add_pattern_filter (mDialog, _("XML files"),
+ "*.xml", (char *) NULL);
+ }
+ if (filterMask & nsIFilePicker::filterXUL)
+ {
+ ephy_file_chooser_add_pattern_filter (mDialog, _("XUL files"),
+ "*.xul", (char *) NULL);
+ }
+
+ return NS_OK;
+}
+
+/* void appendFilter (in AString title, in AString filter); */
+#ifdef MOZ_NSIFILEPICKER_NSASTRING_
+NS_IMETHODIMP GFilePicker::AppendFilter(const nsAString& title, const nsAString& filter)
+#else
+NS_IMETHODIMP GFilePicker::AppendFilter(const PRUnichar *title, const PRUnichar *filter)
+#endif
+{
+ NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);
+
+ LOG ("GFilePicker::AppendFilter");
+
+#ifdef MOZ_NSIFILEPICKER_NSASTRING_
+ if (!filter.Length()) return NS_ERROR_FAILURE;
+#else
+ if (!filter) return NS_ERROR_FAILURE;
+#endif
+
+ nsCString pattern;
+#ifdef MOZ_NSIFILEPICKER_NSASTRING_
+ NS_UTF16ToCString (filter, NS_CSTRING_ENCODING_UTF8, pattern);
+#else
+ NS_UTF16ToCString (nsString(filter), NS_CSTRING_ENCODING_UTF8, pattern);
+#endif
+
+ char **patterns;
+ patterns = g_strsplit (pattern.get(), ";", -1);
+ if (!patterns) return NS_ERROR_FAILURE;
+
+ GtkFileFilter *filth;
+ filth = gtk_file_filter_new ();
+
+ for (int i = 0; patterns[i] != NULL; i++)
+ {
+ gtk_file_filter_add_pattern (filth, g_strstrip (patterns[i]));
+ }
+
+ nsCString cTitle;
+#ifdef MOZ_NSIFILEPICKER_NSASTRING_
+ NS_UTF16ToCString (title, NS_CSTRING_ENCODING_UTF8, cTitle);
+#else
+ NS_UTF16ToCString (nsString(title), NS_CSTRING_ENCODING_UTF8, cTitle);
+#endif
+
+ gtk_file_filter_set_name (filth, cTitle.get());
+
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (mDialog), filth);
+
+ g_strfreev (patterns);
+
+ return NS_OK;
+}
+
+/* attribute AString defaultString; */
+#ifdef MOZ_NSIFILEPICKER_NSASTRING_
+NS_IMETHODIMP GFilePicker::GetDefaultString(nsAString& aDefaultString)
+#else
+NS_IMETHODIMP GFilePicker::GetDefaultString(PRUnichar **aDefaultString)
+#endif
+{
+ NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);
+
+ LOG ("GFilePicker::GetDefaultString");
+
+#ifdef MOZ_NSIFILEPICKER_NSASTRING_
+ aDefaultString = mDefaultString;
+#else
+ *aDefaultString = NS_StringCloneData (mDefaultString);
+#endif
+
+ return NS_OK;
+}
+
+#ifdef MOZ_NSIFILEPICKER_NSASTRING_
+NS_IMETHODIMP GFilePicker::SetDefaultString(const nsAString& aDefaultString)
+#else
+NS_IMETHODIMP GFilePicker::SetDefaultString(const PRUnichar *aDefaultString)
+#endif
+{
+ NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);
+
+ mDefaultString.Assign (aDefaultString);
+
+ if (mMode == nsIFilePicker::modeSave)
+ {
+ nsCString defaultString;
+ NS_UTF16ToCString (mDefaultString, NS_CSTRING_ENCODING_UTF8,
+ defaultString);
+
+ LOG ("GFilePicker::SetDefaultString %s", defaultString.get());
+
+ if (!defaultString.Length()) return NS_ERROR_FAILURE;
+
+ /* set_current_name takes UTF-8, not a filename */
+ gtk_file_chooser_set_current_name
+ (GTK_FILE_CHOOSER (mDialog), defaultString.get());
+ }
+
+ return NS_OK;
+}
+
+/* attribute AString defaultExtension; */
+#ifdef MOZ_NSIFILEPICKER_NSASTRING_
+NS_IMETHODIMP GFilePicker::GetDefaultExtension(nsAString& aDefaultExtension)
+#else
+NS_IMETHODIMP GFilePicker::GetDefaultExtension(PRUnichar **aDefaultExtension)
+#endif
+{
+ LOG ("GFilePicker::GetDefaultExtension");
+
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#ifdef MOZ_NSIFILEPICKER_NSASTRING_
+NS_IMETHODIMP GFilePicker::SetDefaultExtension(const nsAString& aDefaultExtension)
+#else
+NS_IMETHODIMP GFilePicker::SetDefaultExtension(const PRUnichar *aDefaultExtension)
+#endif
+{
+ LOG ("GFilePicker::SetDefaultExtension");
+
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute long filterIndex; */
+NS_IMETHODIMP GFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
+{
+ LOG ("GFilePicker::GetFilterIndex");
+
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP GFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
+{
+ LOG ("GFilePicker::SetFilterIndex index=%d", aFilterIndex);
+
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute nsILocalFile displayDirectory; */
+NS_IMETHODIMP GFilePicker::GetDisplayDirectory(nsILocalFile **aDisplayDirectory)
+{
+ NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);
+
+ LOG ("GFilePicker::GetDisplayDirectory");
+
+ char *dir = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (mDialog));
+
+ if (dir != NULL)
+ {
+ nsCOMPtr<nsILocalFile> file = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
+ file->InitWithNativePath (nsCString (dir));
+ NS_IF_ADDREF (*aDisplayDirectory = file);
+
+ g_free (dir);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP GFilePicker::SetDisplayDirectory(nsILocalFile *aDisplayDirectory)
+{
+ NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);
+
+ nsCString dir;
+ aDisplayDirectory->GetNativePath (dir);
+
+ LOG ("GFilePicker::SetDisplayDirectory to %s", dir.get());
+
+ if (mDefaultString.Length() && mMode != nsIFilePicker::modeSave)
+ {
+ nsCString defaultString;
+ NS_UTF16ToCString (mDefaultString, NS_CSTRING_ENCODING_NATIVE_FILESYSTEM,
+ defaultString);
+
+ char *filename = g_build_filename (dir.get(), defaultString.get(), (char *) NULL);
+ LOG ("Setting filename to %s", filename);
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (mDialog), filename);
+ g_free (filename);
+ }
+ else
+ {
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (mDialog),
+ dir.get());
+ }
+
+ return NS_OK;
+}
+
+/* readonly attribute nsILocalFile file; */
+NS_IMETHODIMP GFilePicker::GetFile(nsILocalFile **aFile)
+{
+ NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);
+
+ char *filename;
+
+ LOG ("GFilePicker::GetFile");
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (mDialog));
+
+ if (filename != NULL)
+ {
+ nsCOMPtr<nsILocalFile> file = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
+ file->InitWithNativePath (nsCString (filename));
+ NS_IF_ADDREF (*aFile = file);
+
+ g_free (filename);
+ }
+
+ return NS_OK;
+}
+
+/* readonly attribute nsIFileURL fileURL; */
+NS_IMETHODIMP GFilePicker::GetFileURL(nsIFileURL **aFileURL)
+{
+ NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);
+
+ LOG ("GFilePicker::GetFileURL");
+
+ nsCOMPtr<nsILocalFile> file;
+ GetFile (getter_AddRefs(file));
+ NS_ENSURE_TRUE (file, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIFileURL> fileURL = do_CreateInstance (NS_STANDARDURL_CONTRACTID);
+ fileURL->SetFile(file);
+ NS_IF_ADDREF(*aFileURL = fileURL);
+
+ return NS_OK;
+}
+
+/* readonly attribute nsISimpleEnumerator files; */
+NS_IMETHODIMP GFilePicker::GetFiles(nsISimpleEnumerator * *aFiles)
+{
+ // Not sure if we need to implement it at all, it's used nowhere
+ // in mozilla, but I guess a javascript might call it?
+
+ LOG ("GFilePicker::GetFiles");
+
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* short show (); */
+NS_IMETHODIMP GFilePicker::Show(PRInt16 *_retval)
+{
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ AutoWindowModalState (mParent);
+ mParent = nsnull;
+
+ LOG ("GFilePicker::Show");
+
+ gtk_window_set_modal (GTK_WINDOW (mDialog), TRUE);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (mDialog), FALSE);
+
+ /* If there's just the "ALL" filter, it's no use showing the filters! */
+ GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (mDialog));
+ if (g_slist_length (filters) == 1)
+ {
+ GtkFileFilter *filter = GTK_FILE_FILTER (filters->data);
+ const char *name = gtk_file_filter_get_name (filter);
+
+ if (!name || strcmp (name, _("All files")) == 0)
+ {
+ gtk_file_chooser_remove_filter (GTK_FILE_CHOOSER (mDialog),
+ filter);
+ }
+ }
+ g_slist_free (filters);
+
+ gtk_widget_show (GTK_WIDGET (mDialog));
+
+ int response;
+ char *filename = NULL;
+
+ do
+ {
+ response = gtk_dialog_run (GTK_DIALOG (mDialog));
+
+ g_free (filename);
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (mDialog));
+
+ LOG ("GFilePicker::Show response=%d, filename=%s", response, filename);
+ }
+ while (response == GTK_RESPONSE_ACCEPT &&
+ mMode == nsIFilePicker::modeSave &&
+ !ephy_gui_check_location_writable (GTK_WIDGET (mDialog), filename));
+
+ gtk_widget_hide (GTK_WIDGET (mDialog));
+
+ if (response == GTK_RESPONSE_ACCEPT && filename != NULL)
+ {
+ *_retval = nsIFilePicker::returnOK;
+ }
+ else
+ {
+ *_retval = nsIFilePicker::returnCancel;
+ }
+
+ g_free (filename);
+
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/FilePicker.h b/embed/xulrunner/embed/FilePicker.h
new file mode 100644
index 000000000..fa63c56b1
--- /dev/null
+++ b/embed/xulrunner/embed/FilePicker.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2001 Philip Langdale
+ * Copyright © 2003 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_FILEPICKER_H
+#define EPHY_FILEPICKER_H
+
+#include <nsIFilePicker.h>
+
+class nsIDOMWindow;
+
+#include "ephy-file-chooser.h"
+
+#define G_FILEPICKER_CID \
+{ /* 3636dc79-0b42-4bad-8a3f-ae15d3671d17 */ \
+ 0x3636dc79, \
+ 0x0b42, \
+ 0x4bad, \
+ {0x8a, 0x3f, 0xae, 0x15, 0xd3, 0x67, 0x1d, 0x17} \
+}
+
+#define G_FILEPICKER_CONTRACTID "@mozilla.org/filepicker;1"
+#define G_FILEPICKER_CLASSNAME "Epiphany File Picker Implementation"
+
+class nsIFactory;
+
+extern nsresult NS_NewFilePickerFactory(nsIFactory** aFactory);
+
+class GFilePicker : public nsIFilePicker
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFILEPICKER
+
+ GFilePicker();
+ virtual ~GFilePicker();
+
+private:
+ EphyFileChooser *mDialog;
+ PRInt16 mMode;
+ nsString mDefaultString;
+ nsCOMPtr<nsIDOMWindow> mParent;
+};
+
+#endif
diff --git a/embed/xulrunner/embed/GeckoCookiePromptService.cpp b/embed/xulrunner/embed/GeckoCookiePromptService.cpp
new file mode 100644
index 000000000..fa33e8bfb
--- /dev/null
+++ b/embed/xulrunner/embed/GeckoCookiePromptService.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright © 2003 Tommi Komulainen <tommi.komulainen@iki.fi>
+ * Copyright © 2004, 2007 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <gtk/gtkbox.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkwindow.h>
+
+#include <nsStringAPI.h>
+
+#include "ephy-debug.h"
+#include "ephy-gui.h"
+
+#include "AutoJSContextStack.h"
+#include "AutoWindowModalState.h"
+#include "EphyUtils.h"
+
+#include "GeckoCookiePromptService.h"
+
+NS_IMPL_ISUPPORTS1 (GeckoCookiePromptService, nsICookiePromptService)
+
+GeckoCookiePromptService::GeckoCookiePromptService()
+{
+ LOG ("GeckoCookiePromptService ctor [%p]", this);
+}
+
+GeckoCookiePromptService::~GeckoCookiePromptService()
+{
+ LOG ("GeckoCookiePromptService dtor [%p]", this);
+}
+
+/* boolean cookieDialog (in nsIDOMWindow parent, in nsICookie cookie, in ACString hostname, in long cookiesFromHost, in boolean changingCookie, inout boolean checkValue); */
+NS_IMETHODIMP
+GeckoCookiePromptService::CookieDialog (nsIDOMWindow *aParent,
+ nsICookie *aCookie,
+ const nsACString &aHostname,
+ PRInt32 aCookiesFromHost,
+ PRBool aChangingCookie,
+ PRBool *_checkValue,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG (aParent);
+ NS_ENSURE_ARG (aCookie);
+ NS_ENSURE_ARG_POINTER (_checkValue);
+ NS_ENSURE_ARG_POINTER (_retval);
+
+ // TODO short-circuit and accept session cookies as per preference
+ // TODO until mozilla starts supporting it natively?
+
+ GtkWidget *parent = EphyUtils::FindGtkParent (aParent);
+ NS_ENSURE_TRUE(parent, NS_ERROR_INVALID_POINTER);
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) {
+ return rv;
+ }
+
+ AutoWindowModalState modalState (aParent);
+
+ nsCString host(aHostname);
+
+ GtkWidget *dialog = gtk_message_dialog_new
+ (GTK_WINDOW (parent),
+ GTK_DIALOG_MODAL /* FIXME mozilla sucks! */,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("Accept cookie from %s?"),
+ host.get());
+ GtkWindow *window = GTK_WINDOW (dialog);
+ GtkDialog *gdialog = GTK_DIALOG (dialog);
+ GtkMessageDialog *message_dialog = GTK_MESSAGE_DIALOG (dialog);
+
+ gtk_window_set_icon_name (window, "web-browser");
+ gtk_window_set_title (window, _("Accept Cookie?"));
+
+ if (aChangingCookie) {
+ gtk_message_dialog_format_secondary_text
+ (message_dialog,
+ _("The site wants to modify an existing cookie."));
+ } else if (aCookiesFromHost == 0) {
+ gtk_message_dialog_format_secondary_text
+ (message_dialog,
+ _("The site wants to set a cookie."));
+ } else if (aCookiesFromHost == 1) {
+ gtk_message_dialog_format_secondary_text
+ (message_dialog,
+ _("The site wants to set a second cookie."));
+ } else {
+ char *num_text = g_strdup_printf
+ (ngettext ("You already have %d cookie from this site.",
+ "You already have %d cookies from this site.",
+ aCookiesFromHost),
+ aCookiesFromHost);
+
+ gtk_message_dialog_format_secondary_text
+ (message_dialog,
+ "The site %s wants to set another cookie. %s",
+ host.get(), num_text);
+ g_free (num_text);
+ }
+
+ GtkWidget *checkbutton;
+ checkbutton = gtk_check_button_new_with_mnemonic
+ (_("Apply this _decision to all cookies from this site"));
+ gtk_widget_show (checkbutton);
+ gtk_box_pack_start (GTK_BOX (ephy_gui_message_dialog_get_content_box (dialog)),
+ checkbutton, FALSE, FALSE, 0);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), *_checkValue);
+
+ gtk_dialog_add_button (gdialog,
+ _("_Reject"), GTK_RESPONSE_REJECT);
+ gtk_dialog_add_button (gdialog,
+ _("_Accept"), GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_default_response (gdialog, GTK_RESPONSE_ACCEPT);
+
+ int response = gtk_dialog_run (gdialog);
+
+ if (response == GTK_RESPONSE_ACCEPT || response == GTK_RESPONSE_REJECT) {
+ *_retval = (response == GTK_RESPONSE_ACCEPT);
+ *_checkValue = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton));
+ } else {
+ /* if the dialog was closed, but no button was pressed,
+ * consider it as 'Reject' but ignore the checkbutton
+ */
+ *_retval = PR_FALSE;
+ *_checkValue = PR_FALSE;
+ }
+
+ gtk_widget_destroy (dialog);
+
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/GeckoCookiePromptService.h b/embed/xulrunner/embed/GeckoCookiePromptService.h
new file mode 100644
index 000000000..7092a2982
--- /dev/null
+++ b/embed/xulrunner/embed/GeckoCookiePromptService.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2003 Tommi Komulainen <tommi.komulainen@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#ifndef COOKIEPROMPTSERVICE_H
+#define COOKIEPROMPTSERVICE_H
+
+#include <nsICookiePromptService.h>
+
+/* 50766a18-0b34-41d9-8f6c-4612200e6556 */
+#define EPHY_COOKIEPROMPTSERVICE_CID \
+ { 0x50766a18, 0x0b34, 0x41d9, { 0x8f, 0x6c, 0x46, 0x12, 0x20, 0x0e, 0x65, 0x56 } }
+
+#define EPHY_COOKIEPROMPTSERVICE_CLASSNAME "Epiphany Cookie Prompt Service"
+#define EPHY_COOKIEPROMPTSERVICE_CONTRACTID "@mozilla.org/embedcomp/cookieprompt-service;1"
+
+class GeckoCookiePromptService : public nsICookiePromptService {
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICOOKIEPROMPTSERVICE
+
+ GeckoCookiePromptService();
+
+ private:
+ ~GeckoCookiePromptService();
+};
+
+#endif /* COOKIEPROMPTSERVICE_H */
diff --git a/embed/xulrunner/embed/GeckoFormSigningDialog.cpp b/embed/xulrunner/embed/GeckoFormSigningDialog.cpp
new file mode 100644
index 000000000..309b3c11e
--- /dev/null
+++ b/embed/xulrunner/embed/GeckoFormSigningDialog.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <glade/glade-xml.h>
+
+#include <nsStringAPI.h>
+
+#include <nsCOMPtr.h>
+#include <nsIDOMWindow.h>
+#include <nsIInterfaceRequestor.h>
+#include <nsIInterfaceRequestorUtils.h>
+
+#include "eel-gconf-extensions.h"
+#include "ephy-debug.h"
+#include "ephy-embed-shell.h"
+#include "ephy-file-helpers.h"
+#include "ephy-prefs.h"
+
+#include "AutoJSContextStack.h"
+#include "AutoWindowModalState.h"
+#include "EphyUtils.h"
+
+#include "GeckoFormSigningDialog.h"
+
+#define LITERAL(s) reinterpret_cast<const nsAString::char_type*>(NS_L(s))
+
+NS_IMPL_ISUPPORTS1 (GeckoFormSigningDialog,
+ nsIFormSigningDialog)
+
+GeckoFormSigningDialog::GeckoFormSigningDialog()
+{
+ LOG ("GeckoFormSigningDialog ctor [%p]", this);
+}
+
+GeckoFormSigningDialog::~GeckoFormSigningDialog()
+{
+ LOG ("GeckoFormSigningDialog dtor [%p]", this);
+}
+
+/* nsIFormSigningDialog implementation */
+
+/* boolean confirmSignText (in nsIInterfaceRequestor ctxt,
+ in AString host,
+ in AString signText,
+ [array, size_is (count)] in wstring certNickList,
+ [array, size_is (count)] in wstring certDetailsList,
+ in PRUint32 count,
+ out PRInt32 selectedIndex,
+ out AString password); */
+NS_IMETHODIMP
+GeckoFormSigningDialog::ConfirmSignText (nsIInterfaceRequestor *ctx,
+ const nsAString & host,
+ const nsAString & signText,
+ const PRUnichar **certNickList,
+ const PRUnichar **certDetailsList,
+ PRUint32 count,
+ PRInt32 *selectedIndex,
+ nsAString &_password,
+ PRBool *_cancelled)
+{
+ /* FIXME: limit |signText| to a sensitlbe length (maybe 100k)? */
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
+ if (!parent) {
+ parent = EphyJSUtils::GetDOMWindowFromCallContext ();
+ g_print ("Fallback window %p\n", (void*)parent.get());
+ }
+ GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
+
+ AutoWindowModalState modalState (parent);
+
+ GladeXML *gxml = glade_xml_new (ephy_file ("form-signing-dialog.glade"),
+ "form_signing_dialog", NULL);
+ g_return_val_if_fail (gxml, NS_ERROR_FAILURE);
+
+ GtkWidget *dialog = glade_xml_get_widget (gxml, "form_signing_dialog");
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (gparent));
+
+ GtkLabel *primary_label = GTK_LABEL (glade_xml_get_widget (gxml, "primary_label"));
+ char *primary = g_strdup_printf (_("The web site “%s” requests that you sign the following text:"),
+ NS_ConvertUTF16toUTF8 (host).get ());
+ gtk_label_set_text (primary_label, primary);
+ g_free (primary);
+
+ GtkTextView *textview = GTK_TEXT_VIEW (glade_xml_get_widget (gxml, "textview"));
+ NS_ConvertUTF16toUTF8 text (signText);
+ gtk_text_buffer_set_text (gtk_text_view_get_buffer (textview),
+ text.get (), text.Length ());
+
+ GtkTable *table = GTK_TABLE (glade_xml_get_widget (gxml, "table"));
+ GtkComboBox *combo = GTK_COMBO_BOX (gtk_combo_box_new_text ());
+ for (PRUint32 i = 0; i < count; ++i) {
+ gtk_combo_box_append_text (combo, NS_ConvertUTF16toUTF8 (certNickList[i]).get ());
+ }
+
+ gtk_combo_box_set_active (combo, 0);
+ gtk_table_attach (table, GTK_WIDGET (combo), 1, 2, 0, 1,
+ GtkAttachOptions (0), GtkAttachOptions (0), 0, 0);
+ gtk_widget_show (GTK_WIDGET (combo));
+
+ /* FIXME: Add "View Certificate" button */
+
+ GtkEntry *password_entry = GTK_ENTRY (glade_xml_get_widget (gxml, "password_entry"));
+
+ GtkWidget *button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("_Sign text"),
+ GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
+ gtk_widget_grab_focus (button);
+
+ /* FIXME: make Sign insensitive for some time (proportional to text length, with maximum?) */
+
+ g_object_unref (gxml);
+
+ int response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ *_cancelled = response != GTK_RESPONSE_ACCEPT;
+
+ if (response == GTK_RESPONSE_ACCEPT) {
+ _password = NS_ConvertUTF8toUTF16 (gtk_entry_get_text (password_entry));
+ *selectedIndex = gtk_combo_box_get_active (combo);
+ }
+
+ gtk_widget_destroy (dialog);
+
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/GeckoFormSigningDialog.h b/embed/xulrunner/embed/GeckoFormSigningDialog.h
new file mode 100644
index 000000000..a4438e9d1
--- /dev/null
+++ b/embed/xulrunner/embed/GeckoFormSigningDialog.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef GECKO_FORMSIGNINGDIALOGS_H
+#define GECKO_FORMSIGNINGDIALOGS_H
+
+#include <nsIFormSigningDialog.h>
+
+/* 4e42a43e-fbc5-40cc-bcbb-8cbc4e2101eb */
+#define GECKO_FORMSIGNINGDIALOGS_CID \
+{ 0x4e42a43e, 0xfbc5, 0x40cc, { 0xbc, 0xbb, 0x8c, 0xbc, 0x4e, 0x21, 0x01, 0xeb } }
+
+#define GECKO_FORMSIGNINGDIALOGS_CLASSNAME "Gecko Form Signing Dialogs"
+
+class GeckoFormSigningDialog : public nsIFormSigningDialog
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFORMSIGNINGDIALOG
+
+ GeckoFormSigningDialog();
+ ~GeckoFormSigningDialog();
+};
+
+#endif /* GECKO_FORMSIGNINGDIALOGS_H */
diff --git a/embed/xulrunner/embed/GeckoPrintService.cpp b/embed/xulrunner/embed/GeckoPrintService.cpp
new file mode 100644
index 000000000..8be8263b9
--- /dev/null
+++ b/embed/xulrunner/embed/GeckoPrintService.cpp
@@ -0,0 +1,756 @@
+/*
+ * Copyright © 2006, 2007 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkprintunixdialog.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkwindow.h>
+#include <glade/glade-xml.h>
+
+#include <nsStringAPI.h>
+
+#include <nsCOMPtr.h>
+#include <nsIDOMWindow.h>
+#include <nsIDOMWindowInternal.h>
+
+#include "eel-gconf-extensions.h"
+#include "ephy-debug.h"
+#include "ephy-embed-shell.h"
+#include "ephy-file-helpers.h"
+#include "ephy-gui.h"
+#include "ephy-prefs.h"
+#include "ephy-stock-icons.h"
+
+#include "AutoJSContextStack.h"
+#include "AutoWindowModalState.h"
+#include "EphyUtils.h"
+#include "GeckoPrintSession.h"
+
+#include "GeckoPrintService.h"
+
+/* Some printing keys */
+
+#define CONF_PRINT_BG_COLORS "/apps/epiphany/dialogs/print_background_colors"
+#define CONF_PRINT_BG_IMAGES "/apps/epiphany/dialogs/print_background_images"
+#define CONF_PRINT_COLOR "/apps/epiphany/dialogs/print_color"
+#define CONF_PRINT_DATE "/apps/epiphany/dialogs/print_date"
+#define CONF_PRINT_PAGE_NUMBERS "/apps/epiphany/dialogs/print_page_numbers"
+#define CONF_PRINT_PAGE_TITLE "/apps/epiphany/dialogs/print_page_title"
+#define CONF_PRINT_PAGE_URL "/apps/epiphany/dialogs/print_page_url"
+
+#define LITERAL(s) reinterpret_cast<const nsAString::char_type*>(NS_L(s))
+
+/* From nsIDeviceContext.h */
+#define NS_ERROR_GFX_PRINTER_BASE (1) /* adjustable :-) */
+#define NS_ERROR_GFX_PRINTER_ACCESS_DENIED \
+ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GFX,NS_ERROR_GFX_PRINTER_BASE+5)
+#define NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND \
+ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GFX,NS_ERROR_GFX_PRINTER_BASE+4)
+
+NS_IMPL_ISUPPORTS1 (GeckoPrintService,
+ nsIPrintingPromptService)
+
+GeckoPrintService::GeckoPrintService()
+{
+ LOG ("GeckoPrintService ctor [%p]", this);
+}
+
+GeckoPrintService::~GeckoPrintService()
+{
+ LOG ("GeckoPrintService dtor [%p]", this);
+}
+
+/* nsIPrintingPromptService implementation */
+
+/* void showPrintDialog (in nsIDOMWindow parent,
+ in nsIWebBrowserPrint webBrowserPrint,
+ in nsIPrintSettings printSettings); */
+NS_IMETHODIMP
+GeckoPrintService::ShowPrintDialog (nsIDOMWindow *aParent,
+ nsIWebBrowserPrint *aWebBrowserPrint,
+ nsIPrintSettings *aSettings)
+{
+ /* Locked down? */
+ if (eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_PRINTING)) {
+ return NS_ERROR_GFX_PRINTER_ACCESS_DENIED;
+ }
+
+ GeckoPrintSession *session = GeckoPrintSession::FromSettings (aSettings);
+ NS_ENSURE_TRUE (session, NS_ERROR_INVALID_POINTER);
+
+ /* Print settings changes disallowed, just translate the settings */
+ if (eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_PRINT_SETUP)) {
+ return PrintUnattended (aParent, aSettings);
+ }
+
+ /* Not locked down, show the dialogue */
+
+ nsresult rv;
+#if 0
+ PRBool haveSelection = PR_FALSE;
+ rv = aSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &haveSelection);
+ NS_ENSURE_SUCCESS (rv, rv);
+#endif
+
+ PRInt16 frameUI = nsIPrintSettings::kFrameEnableAll;
+ rv = aSettings->GetHowToEnableFrameUI (&frameUI);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ GtkWidget *parent = EphyUtils::FindGtkParent (aParent);
+ NS_ENSURE_TRUE(parent, NS_ERROR_INVALID_POINTER);
+
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) {
+ return rv;
+ }
+
+ AutoWindowModalState modalState (aParent);
+
+ EphyEmbedShell *shell = ephy_embed_shell_get_default ();
+
+ GladeXML *xml = glade_xml_new (ephy_file ("print.glade"),
+ "print_dialog_custom_tab", NULL);
+ if (!xml) {
+ return NS_ERROR_FAILURE;
+ }
+
+ /* Build the custom tab */
+ GtkWidget *custom_tab = glade_xml_get_widget (xml, "custom_tab_container");
+ ephy_gui_connect_checkbutton_to_gconf (glade_xml_get_widget (xml, "print_bg_colors_checkbutton"), CONF_PRINT_BG_COLORS);
+ ephy_gui_connect_checkbutton_to_gconf (glade_xml_get_widget (xml, "print_bg_images_checkbutton"), CONF_PRINT_BG_IMAGES);
+ ephy_gui_connect_checkbutton_to_gconf (glade_xml_get_widget (xml, "print_date_checkbutton"), CONF_PRINT_DATE);
+ ephy_gui_connect_checkbutton_to_gconf (glade_xml_get_widget (xml, "print_page_numbers_checkbutton"), CONF_PRINT_PAGE_NUMBERS);
+ ephy_gui_connect_checkbutton_to_gconf (glade_xml_get_widget (xml, "print_page_title_checkbutton"), CONF_PRINT_PAGE_TITLE);
+ ephy_gui_connect_checkbutton_to_gconf (glade_xml_get_widget (xml, "print_page_url_checkbutton"), CONF_PRINT_PAGE_URL);
+
+ GtkWidget *frame_box = glade_xml_get_widget (xml, "frame_box");
+ GtkWidget *print_frames_normal = glade_xml_get_widget (xml, "print_frames_normal");
+ GtkWidget *print_frames_selected = glade_xml_get_widget (xml, "print_frames_selected");
+ GtkWidget *print_frames_separately = glade_xml_get_widget (xml, "print_frames_separately");
+
+ /* FIXME: store/load from pref */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (print_frames_normal), TRUE);
+
+ if (frameUI == nsIPrintSettings::kFrameEnableAll) {
+ /* Allow all frame options */
+ gtk_widget_set_sensitive (frame_box, TRUE);
+ } else if (frameUI == nsIPrintSettings::kFrameEnableAsIsAndEach) {
+ /* Allow all except "selected frame" */
+ gtk_widget_set_sensitive (frame_box, TRUE);
+ gtk_widget_set_sensitive (print_frames_selected, FALSE);
+ /* Preselect this one, since the default above only prints _one page_ ! */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (print_frames_separately), TRUE);
+ }
+
+ /* FIXME: this sucks! find some way to do all of this async! */
+ GtkWidget *dialog = gtk_print_unix_dialog_new (NULL /* FIXME title */,
+ GTK_WINDOW (parent));
+ GtkPrintUnixDialog *print_dialog = GTK_PRINT_UNIX_DIALOG (dialog);
+
+ GtkPrintCapabilities capabilities =
+ GtkPrintCapabilities (GTK_PRINT_CAPABILITY_PAGE_SET |
+ GTK_PRINT_CAPABILITY_COPIES |
+ GTK_PRINT_CAPABILITY_COLLATE |
+ GTK_PRINT_CAPABILITY_REVERSE |
+ GTK_PRINT_CAPABILITY_SCALE |
+ GTK_PRINT_CAPABILITY_GENERATE_PS);
+#if 0 //def HAVE_GECKO_1_9
+ capabilities = GtkPrintCapabilities (capabilities | GTK_PRINT_CAPABILITY_GENERATE_PDF);
+#endif
+ gtk_print_unix_dialog_set_manual_capabilities (print_dialog, capabilities);
+
+ gtk_print_unix_dialog_set_page_setup (print_dialog,
+ ephy_embed_shell_get_page_setup (shell));
+ gtk_print_unix_dialog_set_settings (print_dialog,
+ ephy_embed_shell_get_print_settings (shell));
+
+ /* Remove custom tab from its dummy window and put it in the print dialogue */
+ g_object_ref_sink (custom_tab);
+ gtk_container_remove (GTK_CONTAINER (custom_tab->parent), custom_tab);
+ gtk_print_unix_dialog_add_custom_tab (print_dialog, custom_tab,
+ gtk_label_new (_("Options"))); /* FIXME better name! */
+ g_object_unref (custom_tab);
+ g_object_unref (xml);
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ int response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_hide (dialog);
+
+ GtkPrinter *printer = gtk_print_unix_dialog_get_selected_printer (print_dialog);
+
+ if (response != GTK_RESPONSE_OK || !printer) {
+ gtk_widget_destroy (dialog);
+
+ return NS_ERROR_ABORT;
+ }
+
+ PRInt16 printFrames = nsIPrintSettings::kNoFrames;
+ if (frameUI != nsIPrintSettings::kFrameEnableNone) {
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (print_frames_normal))) {
+ printFrames = nsIPrintSettings::kFramesAsIs;
+ } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (print_frames_selected))) {
+ printFrames = nsIPrintSettings::kSelectedFrame;
+ } if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (print_frames_separately))) {
+ printFrames = nsIPrintSettings::kEachFrameSep;
+ }
+ }
+
+ GtkPageSetup *pageSetup = gtk_print_unix_dialog_get_page_setup (print_dialog); /* no reference owned */
+ ephy_embed_shell_set_page_setup (shell, pageSetup);
+
+ GtkPrintSettings *settings = gtk_print_unix_dialog_get_settings (print_dialog);
+ ephy_embed_shell_set_print_settings (shell, settings);
+
+ /* We copy the setup and settings so we can modify them to unset
+ * options handled by gecko.
+ */
+ GtkPageSetup *pageSetupCopy = gtk_page_setup_copy (pageSetup);
+ pageSetup = pageSetupCopy;
+
+ GtkPrintSettings *settingsCopy = gtk_print_settings_copy (settings);
+ g_object_unref (settings);
+ settings = settingsCopy;
+
+ rv = session->SetSettings (aSettings, settings, pageSetup, printer);
+
+ /* Now translate the settings to nsIPrintSettings */
+ if (NS_SUCCEEDED (rv)) {
+ nsCString sourceFile;
+ session->GetSourceFile (sourceFile);
+ if (!sourceFile.IsEmpty ()) {
+ rv = TranslateSettings (settings, pageSetup, printer, sourceFile, printFrames, PR_TRUE, aSettings);
+ } else {
+ rv = NS_ERROR_FAILURE;
+ }
+ }
+
+ gtk_widget_destroy (dialog);
+
+ g_object_unref (settings);
+ g_object_unref (pageSetup);
+
+ return rv;
+}
+
+/* void showProgress (in nsIDOMWindow parent,
+ in nsIWebBrowserPrint webBrowserPrint,
+ in nsIPrintSettings printSettings,
+ in nsIObserver openDialogObserver,
+ in boolean isForPrinting,
+ out nsIWebProgressListener webProgressListener,
+ out nsIPrintProgressParams printProgressParams,
+ out boolean notifyOnOpen); */
+NS_IMETHODIMP
+GeckoPrintService::ShowProgress (nsIDOMWindow *aParent,
+ nsIWebBrowserPrint *aWebBrowserPrint,
+ nsIPrintSettings *aPrintSettings,
+ nsIObserver *aOpenDialogObserver,
+ PRBool aIsForPrinting,
+ nsIWebProgressListener **_webProgressListener,
+ nsIPrintProgressParams **_printProgressParams,
+ PRBool *_notifyOnOpen)
+{
+ /* Print preview */
+ if (!aIsForPrinting) {
+ return NS_OK;
+ }
+
+ nsresult rv;
+ nsCOMPtr<nsIDOMWindowInternal> domWin (do_QueryInterface (aParent, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIPrintSession> session;
+ rv = aPrintSettings->GetPrintSession (getter_AddRefs (session));
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && session, nsnull);
+
+ nsCOMPtr<nsIPrintProgress> progress (do_QueryInterface (session, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ /* Our print session implements those interfaces */
+ rv = CallQueryInterface (session, _webProgressListener);
+ rv |= CallQueryInterface (session, _printProgressParams);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ /* Setting this to PR_FALSE will make gecko immediately start printing
+ * when we return from this function.
+ * If we set this to PR_TRUE, we need to call aOpenDialogObserver::Observe
+ * (topic, subject and data don't matter) when we're ready for printing.
+ */
+ *_notifyOnOpen = PR_FALSE;
+
+ return progress->OpenProgressDialog (domWin, nsnull, nsnull, aOpenDialogObserver, _notifyOnOpen);
+}
+
+/* void showPageSetup (in nsIDOMWindow parent,
+ in nsIPrintSettings printSettings,
+ in nsIObserver aObs); */
+NS_IMETHODIMP GeckoPrintService::ShowPageSetup (nsIDOMWindow *aParent,
+ nsIPrintSettings *aPrintSettings,
+ nsIObserver *aObserver)
+{
+ /* This function is never called from gecko code */
+#if 0
+ /* Locked down? */
+ if (eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_PRINTING) ||
+ eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_PRINT_SETUP)) {
+ return NS_ERROR_ABORT;
+ }
+
+ GtkWidget *parent = EphyUtils::FindGtkParent (aParent);
+ NS_ENSURE_TRUE(parent, NS_ERROR_INVALID_POINTER);
+
+ AutoJSContextStack stack;
+ nsresult rv = stack.Init ();
+ if (NS_FAILED (rv)) {
+ return rv;
+ }
+
+ AutoWindowModalState modalState (aParent);
+
+ EphyEmbedShell *shell = ephy_embed_shell_get_default ();
+ GtkPageSetup *new_setup =
+ gtk_print_run_page_setup_dialog (GTK_WINDOW (parent),
+ ephy_embed_shell_get_page_setup (shell),
+ ephy_embed_shell_get_print_settings (shell));
+ if (new_setup) {
+ ephy_embed_shell_set_page_setup (shell, new_setup);
+ g_object_unref (new_setup);
+ }
+
+ /* FIXME do we need to notify aObserver somehow? */
+ return NS_OK;
+#endif
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void showPrinterProperties (in nsIDOMWindow parent,
+ in wstring printerName,
+ in nsIPrintSettings printSettings); */
+NS_IMETHODIMP
+GeckoPrintService::ShowPrinterProperties (nsIDOMWindow *aParent,
+ const PRUnichar *aPrinterName,
+ nsIPrintSettings *aPrintSettings)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* Private methods */
+
+#if 0
+typedef struct
+{
+ GMainLoop *mainLoop;
+ GtkPrinter *mPrinter;
+ guint timeout;
+ int response;
+ guint cancelled : 1;
+} FindPrinterData;
+
+static void
+FreeFindPrinterData (FindPrinterData *data)
+{
+ if (data->printer) {
+ g_object_unref (data->printer);
+ }
+}
+
+static void
+DialogResponseCallback (GtkWidget *aDialog,
+ int aResponse,
+ FindPrinterData *data)
+{
+ data->response = aResponse;
+ g_main_loop_quit (data->mainloop);
+}
+
+static void
+TimeoutCallback (FindPrinterData *data)
+{
+ data->cancelled = TRUE;
+ g_main_loop_quit (data->mainLoop);
+ data->mainLoop = NULL;
+ return FALSE;
+}
+
+static gboolean
+PrinterEnumerateCallback (GtkPrinter *aPrinter,
+ FindPrinterData *data)
+{
+ if (data->cancelled)
+ return TRUE;
+
+ if ((data->printerName &&
+ strcmp (data->printerName, gtk_printer_get_name (aPrinter)) == 0) ||
+ (!data->printerName &&
+ gtk_printer_is_default (aPrinter))) {
+ data->printer = g_object_ref (aPrinter);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+#endif
+
+nsresult
+GeckoPrintService::PrintUnattended (nsIDOMWindow *aParent,
+ nsIPrintSettings *aPrintSettings)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+#if 0
+ GtkWidget *parent = EphyUtils::FindGtkParent (aParent);
+ NS_ENSURE_TRUE(parent, NS_ERROR_INVALID_POINTER);
+
+ PRBool isCalledFromScript = EphyJSUtils::IsCalledFromScript ();
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) {
+ return rv;
+ }
+
+ AutoWindowModalState modalState (aParent);
+
+ EphyEmbedShell *shell = ephy_embed_shell_get_default ();
+ GtkPrintSettings *settings = ephy_embed_shell_get_print_settings (shell);
+ NS_ENSURE_TRUE (settings, NS_ERROR_FAILURE);
+
+ const char *printer = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_PRINTER);
+#if 0
+ if (!printer || !printer[0]) {
+ return NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND;
+ }
+#endif
+ /* We need to find the printer, so we need to run a mainloop.
+ * If called from a script, give the user a way to cancel the print;
+ * otherwise we'll just show a generic progress message.
+ */
+ GtkWidget *dialog;
+ if (isCalledFromScript) {
+ dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
+ GtkDialogFlags (0),
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_CANCEL,
+ "%s", _("Print this page?"));
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_PRINT,
+ GTK_RESPONSE_ACCEPT);
+ } else {
+ dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
+ GtkDialogFlags (0),
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_CANCEL,
+ "%s", _("Preparing to print"));
+ }
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ FindPrinterData *data = g_new0 (PrinterData, 1);
+ data->dialog = dialog;
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (DialogResponseCallback), data);
+
+ /* Don't run forever */
+ data->timeoutId = g_timeout_add (PRINTER_ENUMERATE_TIMEOUT,
+ (GSourceFunc) EnumerateTimoutCallback,
+ data);
+ /* Enumerate printers until we find our printer */
+ gtk_enumerate_printers ((GtkPrinterFunc) PrinterEnumerateCallback,
+ data,
+ (GDestroyNotify) EnumerateDestroyCallback, FALSE);
+
+ /* Now run the mainloop */
+ int response = gtk_dialog_run (GTK_DIALOG (dialog));
+ Printer
+ gtk_widget_destroy (dialog);
+
+ if (response != GTK_RESPONSE_ACCEPT) {
+ return NS_ERROR_ABORT;
+ }
+
+ nsCString sourceFile;
+ session->GetSourceFile (sourceFile);
+ if (!sourceFile.IsEmpty ()) {
+ rv = TranslateSettings (settings,
+ ephy_embed_shell_get_page_setup (shell),
+ sourceFile, PR_TRUE, aSettings);
+ } else {
+ rv = NS_ERROR_FAILURE;
+ }
+
+ return rv;
+ }
+#endif /* if 0 */
+}
+
+/* Static methods */
+
+/* static */ nsresult
+GeckoPrintService::TranslateSettings (GtkPrintSettings *aGtkSettings,
+ GtkPageSetup *aPageSetup,
+ GtkPrinter *aPrinter,
+ const nsACString &aSourceFile,
+ PRInt16 aPrintFrames,
+ PRBool aIsForPrinting,
+ nsIPrintSettings *aSettings)
+{
+ NS_ENSURE_ARG (aPrinter);
+ NS_ENSURE_ARG (aGtkSettings);
+ NS_ENSURE_ARG (aPageSetup);
+
+#if 0
+ /* Locked down? */
+ if (gtk_print_settings_get_print_to_file (aGtkSettings) &&
+ eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_SAVE_TO_DISK)) {
+ return NS_ERROR_GFX_PRINTER_ACCESS_DENIED;
+ }
+#endif
+
+ GtkPrintCapabilities capabilities = gtk_printer_get_capabilities (aPrinter);
+
+ /* Initialisation */
+ aSettings->SetIsInitializedFromPrinter (PR_FALSE); /* FIXME: PR_TRUE? */
+ aSettings->SetIsInitializedFromPrefs (PR_FALSE); /* FIXME: PR_TRUE? */
+ aSettings->SetPrintSilent (PR_FALSE);
+ aSettings->SetShowPrintProgress (PR_TRUE);
+
+ /* We always print PS to a file and then hand that off to gtk-print */
+ aSettings->SetPrinterName (LITERAL ("PostScript/default"));
+
+ if (aIsForPrinting) {
+ aSettings->SetPrintToFile (PR_TRUE);
+
+ nsString sourceFile;
+ NS_CStringToUTF16 (aSourceFile,
+ NS_CSTRING_ENCODING_NATIVE_FILESYSTEM,
+ sourceFile);
+
+ aSettings->SetToFileName (sourceFile.get ());
+ } else {
+ /* Otherwise mozilla will create the file nevertheless and
+ * fail since we haven't set a name!
+ */
+ aSettings->SetPrintToFile (PR_FALSE);
+ }
+
+ /* This is the time between printing each page, in ms.
+ * It 'gives the user more time to press cancel' !
+ * We don't want any of this nonsense, so set this to a low value,
+ * just enough to update the print dialogue.
+ */
+ aSettings->SetPrintPageDelay (50);
+
+ if (aIsForPrinting) {
+#if 0 //def HAVE_GECKO_1_9
+ NS_ENSURE_TRUE (aPrinter, NS_ERROR_FAILURE);
+
+ const char *format = gtk_print_settings_get (aGtkSettings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT);
+ if (!format)
+ format = "ps";
+
+ if (strcmp (format, "pdf") == 0 &&
+ gtk_printer_accepts_pdf (aPrinter)) {
+ aSettings->SetOutputFormat (nsIPrintSettings::kOutputFormatPDF);
+ } else if (strcmp (format, "ps") == 0 &&
+ gtk_printer_accepts_ps (aPrinter)) {
+ aSettings->SetOutputFormat (nsIPrintSettings::kOutputFormatPS);
+ } else {
+ g_warning ("Output format '%s' specified, but printer '%s' does not support it!",
+ format, gtk_printer_get_name (aPrinter));
+ return NS_ERROR_FAILURE;
+ }
+#endif
+
+ int n_copies = gtk_print_settings_get_n_copies (aGtkSettings);
+ if (n_copies <= 0)
+ return NS_ERROR_FAILURE;
+ if (capabilities & GTK_PRINT_CAPABILITY_COPIES) {
+ aSettings->SetNumCopies (1);
+ } else {
+ /* We have to copy them ourself */
+ aSettings->SetNumCopies (n_copies);
+ gtk_print_settings_set_n_copies (aGtkSettings, 1);
+ }
+
+ gboolean reverse = gtk_print_settings_get_reverse (aGtkSettings);
+ if (capabilities & GTK_PRINT_CAPABILITY_REVERSE) {
+ aSettings->SetPrintReversed (PR_FALSE);
+ } else {
+ aSettings->SetPrintReversed (reverse);
+ gtk_print_settings_set_reverse (aGtkSettings, FALSE);
+ }
+
+ GtkPageSet pageSet = gtk_print_settings_get_page_set (aGtkSettings);
+ aSettings->SetPrintOptions (nsIPrintSettings::kPrintEvenPages,
+ pageSet != GTK_PAGE_SET_ODD);
+ aSettings->SetPrintOptions (nsIPrintSettings::kPrintEvenPages,
+ pageSet != GTK_PAGE_SET_EVEN);
+
+ GtkPrintPages printPages = gtk_print_settings_get_print_pages (aGtkSettings);
+ switch (printPages) {
+ case GTK_PRINT_PAGES_RANGES: {
+ int numRanges = 0;
+ GtkPageRange *pageRanges = gtk_print_settings_get_page_ranges (aGtkSettings, &numRanges);
+ if (numRanges > 0) {
+ /* FIXME: We can only support one range, ignore more ranges or raise error? */
+ aSettings->SetPrintRange (nsIPrintSettings::kRangeSpecifiedPageRange);
+ /* Gecko page numbers start at 1, while gtk page numbers start at 0 */
+ aSettings->SetStartPageRange (pageRanges[0].start + 1);
+ aSettings->SetEndPageRange (pageRanges[0].end + 1);
+
+ g_free (pageRanges);
+ break;
+ }
+ /* Fall-through to PAGES_ALL */
+ }
+ case GTK_PRINT_PAGES_CURRENT:
+ /* not supported, fall through */
+ case GTK_PRINT_PAGES_ALL:
+ aSettings->SetPrintRange (nsIPrintSettings::kRangeAllPages);
+ break;
+ /* FIXME: we need some custom ranges here, "Selection" and "Focused Frame" */
+ }
+ } else {
+ aSettings->SetPrintOptions (nsIPrintSettings::kPrintEvenPages, PR_TRUE);
+ aSettings->SetPrintOptions (nsIPrintSettings::kPrintEvenPages, PR_TRUE);
+ aSettings->SetPrintReversed (PR_FALSE);
+ aSettings->SetPrintRange (nsIPrintSettings::kRangeAllPages);
+ }
+
+ /* And clear those in the settings, so the printer doesn't try to apply them too */
+ gtk_print_settings_set_print_pages (aGtkSettings, GTK_PRINT_PAGES_ALL);
+ gtk_print_settings_set_page_ranges (aGtkSettings, NULL, 0);
+ gtk_print_settings_set_page_set (aGtkSettings, GTK_PAGE_SET_ALL);
+
+ switch (gtk_print_settings_get_orientation (aGtkSettings)) {
+ case GTK_PAGE_ORIENTATION_PORTRAIT:
+ case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT: /* not supported */
+ aSettings->SetOrientation (nsIPrintSettings::kPortraitOrientation);
+ break;
+ case GTK_PAGE_ORIENTATION_LANDSCAPE:
+ case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE: /* not supported */
+ aSettings->SetOrientation (nsIPrintSettings::kLandscapeOrientation);
+ break;
+ }
+
+ aSettings->SetPrintInColor (gtk_print_settings_get_use_color (aGtkSettings));
+
+ aSettings->SetPaperSizeUnit(nsIPrintSettings::kPaperSizeMillimeters);
+ aSettings->SetPaperSize (nsIPrintSettings::kPaperSizeDefined);
+
+ GtkPaperSize *paperSize = gtk_page_setup_get_paper_size (aPageSetup);
+ if (!paperSize) {
+ return NS_ERROR_FAILURE;
+ }
+
+ aSettings->SetPaperSizeType (nsIPrintSettings::kPaperSizeDefined);
+ aSettings->SetPaperWidth (gtk_paper_size_get_width (paperSize, GTK_UNIT_MM));
+ aSettings->SetPaperHeight (gtk_paper_size_get_height (paperSize, GTK_UNIT_MM));
+
+#ifdef HAVE_GECKO_1_9
+ aSettings->SetPaperName (NS_ConvertUTF8toUTF16 (gtk_paper_size_get_name (paperSize)).get ());
+#else
+{
+ /* Mozilla bug https://bugzilla.mozilla.org/show_bug.cgi?id=307404
+ * means that we cannot actually use any paper sizes except mozilla's
+ * builtin list, and we must refer to them *by name*!
+ */
+ static const struct {
+ const char gtkPaperName[13];
+ const char mozPaperName[10];
+ } paperTable [] = {
+ { GTK_PAPER_NAME_A5, "A5" },
+ { GTK_PAPER_NAME_A4, "A4" },
+ { GTK_PAPER_NAME_A3, "A3" },
+ { GTK_PAPER_NAME_LETTER, "Letter" },
+ { GTK_PAPER_NAME_LEGAL, "Legal" },
+ { GTK_PAPER_NAME_EXECUTIVE, "Executive" },
+ };
+
+ const char *paperName = gtk_paper_size_get_name (paperSize);
+
+ PRUint32 i;
+ for (i = 0; i < G_N_ELEMENTS (paperTable); i++) {
+ if (g_ascii_strcasecmp (paperTable[i].gtkPaperName, paperName) == 0) {
+ paperName = paperTable[i].mozPaperName;
+ break;
+ }
+ }
+ if (i == G_N_ELEMENTS (paperTable)) {
+ /* Not in table, fall back to A4 */
+ g_warning ("Unknown paper name '%s', falling back to A4", gtk_paper_size_get_name (paperSize));
+ paperName = paperTable[1].mozPaperName;
+ }
+
+ aSettings->SetPaperName (NS_ConvertUTF8toUTF16 (paperName).get ());
+}
+#endif /* !HAVE_GECKO_1_9 */
+
+ /* Sucky mozilla wants margins in inch! */
+ aSettings->SetMarginTop (gtk_page_setup_get_top_margin (aPageSetup, GTK_UNIT_INCH));
+ aSettings->SetMarginBottom (gtk_page_setup_get_bottom_margin (aPageSetup, GTK_UNIT_INCH));
+ aSettings->SetMarginLeft (gtk_page_setup_get_left_margin (aPageSetup, GTK_UNIT_INCH));
+ aSettings->SetMarginRight (gtk_page_setup_get_right_margin (aPageSetup, GTK_UNIT_INCH));
+
+ aSettings->SetHeaderStrLeft (eel_gconf_get_boolean (CONF_PRINT_PAGE_TITLE) ? LITERAL ("&T") : LITERAL (""));
+ aSettings->SetHeaderStrCenter (LITERAL (""));
+ aSettings->SetHeaderStrRight (eel_gconf_get_boolean (CONF_PRINT_PAGE_URL) ? LITERAL ("&U") : LITERAL (""));
+ aSettings->SetFooterStrLeft (eel_gconf_get_boolean (CONF_PRINT_PAGE_NUMBERS) ? LITERAL ("&PT") : LITERAL (""));
+ aSettings->SetFooterStrCenter (LITERAL (""));
+ aSettings->SetFooterStrRight (eel_gconf_get_boolean (CONF_PRINT_DATE) ? LITERAL ("&D") : LITERAL (""));
+
+ aSettings->SetPrintFrameType (aPrintFrames);
+ aSettings->SetPrintFrameTypeUsage (nsIPrintSettings::kUseSettingWhenPossible);
+
+ /* FIXME: only if GTK_PRINT_CAPABILITY_SCALE is not set? */
+ aSettings->SetScaling (gtk_print_settings_get_scale (aGtkSettings) / 100.0);
+ gtk_print_settings_set_scale (aGtkSettings, 1.0);
+
+ aSettings->SetShrinkToFit (PR_FALSE); /* FIXME setting */
+
+ aSettings->SetPrintBGColors (eel_gconf_get_boolean (CONF_PRINT_BG_COLORS) != FALSE);
+ aSettings->SetPrintBGImages (eel_gconf_get_boolean (CONF_PRINT_BG_IMAGES) != FALSE);
+
+ /* aSettings->SetPlexName (LITERAL ("default")); */
+ /* aSettings->SetColorspace (LITERAL ("default")); */
+ /* aSettings->SetResolutionName (LITERAL ("default")); */
+ /* aSettings->SetDownloadFonts (PR_TRUE); */
+
+ /* Unset those setting that we can handle, so they don't get applied
+ * again for the print job.
+ */
+ /* gtk_print_settings_set_collate (aGtkSettings, FALSE); not yet */
+ /* FIXME: Unset the orientation for the print job? */
+ /* gtk_print_settings_set_orientation (aGtkSettings, GTK_PAGE_ORIENTATION_PORTRAIT); */
+ /* FIXME: unset output format -> "ps" ? */
+
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/GeckoPrintService.h b/embed/xulrunner/embed/GeckoPrintService.h
new file mode 100644
index 000000000..c2e21cf3e
--- /dev/null
+++ b/embed/xulrunner/embed/GeckoPrintService.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef GECKO_PRINT_SERVICE_H
+#define GECKO_PRINT_SERVICE_H
+
+#include <gtk/gtkpagesetup.h>
+#include <gtk/gtkprintsettings.h>
+#include <gtk/gtkprinter.h>
+
+#include <nsIPrintingPromptService.h>
+
+class nsIPrintSettings;
+
+/* 6a71ff30-7f4d-4d91-b71a-d5c9764b34be */
+#define GECKO_PRINT_SERVICE_IID \
+{ 0x6a71ff30, 0x7f4d, 0x4d91, \
+ { 0xb7, 0x1a, 0xd5, 0xc9, 0x76, 0x4b, 0x34, 0xbe } }
+
+#define GECKO_PRINT_SERVICE_CLASSNAME "Gecko Print Service"
+
+class GeckoPrintService : public nsIPrintingPromptService
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPRINTINGPROMPTSERVICE
+
+ GeckoPrintService();
+ virtual ~GeckoPrintService();
+
+ static nsresult TranslateSettings (GtkPrintSettings*, GtkPageSetup *, GtkPrinter *, const nsACString&, PRInt16, PRBool, nsIPrintSettings*);
+
+private:
+ nsresult PrintUnattended (nsIDOMWindow *, nsIPrintSettings *);
+};
+
+#endif /* GECKO_PRINT_SERVICE_H */
diff --git a/embed/xulrunner/embed/GeckoPrintSession.cpp b/embed/xulrunner/embed/GeckoPrintSession.cpp
new file mode 100644
index 000000000..ddf968283
--- /dev/null
+++ b/embed/xulrunner/embed/GeckoPrintSession.cpp
@@ -0,0 +1,629 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <unistd.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <nsStringAPI.h>
+
+#include <nsIDOMWindow.h>
+#include <nsIDOMWindowInternal.h>
+#include <nsIPrintSettings.h>
+
+#include "ephy-debug.h"
+#include "ephy-embed-shell.h"
+#include "ephy-file-helpers.h"
+
+#include "EphyUtils.h"
+
+#include "GeckoPrintSession.h"
+
+#define MAX_STRING_LENGTH 512
+
+GeckoPrintSession::GeckoPrintSession ()
+: mSettings(NULL)
+, mPageSetup(NULL)
+, mPrinter(NULL)
+, mJob(NULL)
+, mProgressDialog(NULL)
+, mTitleLabel(NULL)
+, mProgressBar(NULL)
+, mStartPrintIdleID(0)
+, mSourceFileIsTemp(PR_FALSE)
+, mDone(PR_FALSE)
+, mCancelled(PR_FALSE)
+{
+ LOG ("GeckoPrintSession ctor [%p]", (void*) this);
+
+ /* FIXME: connect to "prepare-close" ? */
+ g_object_ref (ephy_embed_shell_get_default ());
+}
+
+GeckoPrintSession::~GeckoPrintSession ()
+{
+ LOG ("GeckoPrintSession dtor [%p]", (void*) this);
+
+ NS_ASSERTION (mStartPrintIdleID == 0, "Impossible");
+
+ if (!mDone && !mCancelled) {
+ Cancel ();
+ }
+ DestroyJob ();
+
+ if (mSettings) {
+ g_object_unref (mSettings);
+ }
+ if (mPageSetup) {
+ g_object_unref (mPageSetup);
+ }
+ if (mPrinter) {
+ g_object_unref (mPrinter);
+ }
+ if (mProgressDialog) {
+ gtk_widget_destroy (mProgressDialog);
+ }
+ if (mSourceFileIsTemp) {
+ unlink (mSourceFile.get ());
+ }
+
+ g_object_unref (ephy_embed_shell_get_default ());
+}
+
+void
+GeckoPrintSession::GetSourceFile (nsACString &aSource)
+{
+ aSource.Assign (mSourceFile);
+}
+
+nsresult
+GeckoPrintSession::SetSettings (nsIPrintSettings *aPrintSettings,
+ GtkPrintSettings *aSettings,
+ GtkPageSetup *aPageSetup,
+ GtkPrinter *aPrinter)
+{
+ NS_ASSERTION (!mPrintSettings && !mSettings && !mPageSetup && !mPrinter, "Already have settings!");
+
+ NS_ENSURE_ARG (aPrintSettings);
+ NS_ENSURE_ARG (aSettings);
+
+ mPrintSettings = aPrintSettings;
+ mSettings = (GtkPrintSettings *) g_object_ref (aSettings);
+
+ NS_ENSURE_ARG (aPageSetup);
+ NS_ENSURE_ARG (aPrinter);
+
+ mPageSetup = (GtkPageSetup *) g_object_ref (aPageSetup);
+ mPrinter = (GtkPrinter *) g_object_ref (aPrinter);
+
+#if 0
+ /* Compute the source file name */
+ if (gtk_print_settings_get_print_to_file (mSettings)) {
+ /* FIXME: support gnome-VFS uris here! */
+ const char *fileURI = gtk_print_settings_get (aSettings, "export-uri");
+ NS_ENSURE_TRUE (fileURI, NS_ERROR_FAILURE);
+
+ char *fileName = g_filename_from_uri (fileURI, NULL, NULL);
+ NS_ENSURE_TRUE (fileURI, NS_ERROR_FAILURE);
+
+ mSourceFile.Assign (fileName);
+ g_free (fileName);
+ } else
+#endif
+ {
+ char *base, *tmpName;
+
+ /* FIXME: use pure glib here (g_mkstemp)! */
+ base = g_build_filename (ephy_file_tmp_dir (), "print-XXXXXX", (const char *) NULL);
+ tmpName = ephy_file_tmp_filename (base, "ps");
+ g_free (base);
+
+ NS_ENSURE_TRUE (tmpName, NS_ERROR_FAILURE);
+ mSourceFile.Assign (tmpName);
+ g_free (tmpName);
+
+ mSourceFileIsTemp = PR_TRUE;
+ }
+
+ return NS_OK;
+}
+
+/* static methods */
+
+/* static */ GeckoPrintSession *
+GeckoPrintSession::FromSettings (nsIPrintSettings *aSettings)
+{
+ nsresult rv;
+ nsCOMPtr<nsIPrintSession> session;
+ rv = aSettings->GetPrintSession (getter_AddRefs (session));
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && session, nsnull);
+
+ /* this is ok since the caller holds a ref to the settings which hold a ref to the session */
+ nsIPrintSession *sessionPtr = session.get();
+ return static_cast<GeckoPrintSession*>(sessionPtr);
+}
+
+/* static functions */
+
+static void
+ReleaseSession (GeckoPrintSession *aSession)
+{
+ NS_RELEASE (aSession);
+}
+
+static gboolean
+ProgressDeleteCallback (GtkDialog *aDialog)
+{
+ gtk_dialog_response (aDialog, GTK_RESPONSE_DELETE_EVENT);
+ return TRUE;
+}
+
+static void
+ProgressResponseCallback (GtkDialog *aDialog,
+ int aResponse,
+ GeckoPrintSession *aSession)
+{
+ aSession->Cancel ();
+}
+
+static gboolean
+StartPrintIdleCallback (GeckoPrintSession *aSession)
+{
+ aSession->StartPrinting ();
+
+ return FALSE;
+}
+
+static void
+JobStatusChangedCallback (GtkPrintJob *aJob,
+ GeckoPrintSession *aSession)
+{
+ aSession->JobStatusChanged ();
+}
+
+static void
+JobCompletedCallback (GtkPrintJob *aJob,
+ GeckoPrintSession *aSession,
+ GError *aError)
+{
+ aSession->JobDone ();
+
+ if (aError) {
+ aSession->JobError (aError->message);
+ }
+}
+
+/* Private methods */
+
+void
+GeckoPrintSession::SetProgress (PRInt32 aCurrent,
+ PRInt32 aMaximum)
+{
+ NS_ENSURE_TRUE (mProgressDialog, );
+
+ if (mCancelled) return;
+
+ /* Mozilla is weird */
+ if (aCurrent > aMaximum || (aCurrent == 100 && aMaximum == 100)) return;
+
+ double fraction = 0.0;
+ if (aMaximum > 0 && aCurrent >= 0) {
+ char *text = g_strdup_printf (_("Page %d of %d"), aCurrent, aMaximum);
+ gtk_progress_bar_set_text (GTK_PROGRESS_BAR (mProgressBar), text);
+ g_free (text);
+
+ fraction = (double) aCurrent / (double) aMaximum;
+ }
+
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (mProgressBar), CLAMP (fraction, 0.0, 1.0));
+}
+
+void
+GeckoPrintSession::SetProgressText (const char *aText)
+{
+ NS_ENSURE_TRUE (mProgressDialog, );
+
+ gtk_progress_bar_set_text (GTK_PROGRESS_BAR (mProgressBar), aText);
+}
+
+void
+GeckoPrintSession::Cancel ()
+{
+ SetProcessCanceledByUser (PR_TRUE);
+
+ if (mProgressDialog) {
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (mProgressDialog),
+ GTK_RESPONSE_CANCEL, FALSE);
+
+ SetProgress (0, 0);
+ SetProgressText (_("Cancelling print")); /* FIXME text! */
+ }
+
+ if (mJob) {
+ /* FIXME: There's no way to cancel mJob! Bug #339323 */
+ }
+}
+
+void
+GeckoPrintSession::StartPrinting ()
+{
+ mStartPrintIdleID = 0;
+
+ GError *error = NULL;
+
+#if 0
+ /* FIXME: this could also be a print job to a file which was
+ * printed to a temp file and now needs to be uploaded to its
+ * final location with gnome-vfs.
+ */
+ if (gtk_print_settings_get_print_to_file (mSettings)) return;
+#endif
+
+ NS_ENSURE_TRUE (mSettings && mPageSetup && mPrinter, );
+
+ mJob = gtk_print_job_new (mTitle.get (),
+ mPrinter,
+ mSettings,
+ mPageSetup);
+ if (!gtk_print_job_set_source_file (mJob, mSourceFile.get (), &error)) {
+ /* FIXME: error dialogue! */
+ g_warning ("Couldn't set print job source: %s", error->message);
+ g_error_free (error);
+
+ g_object_unref (mJob);
+ mJob = NULL;
+
+ return;
+ }
+
+ g_signal_connect (mJob, "status-changed",
+ G_CALLBACK (JobStatusChangedCallback), this);
+
+ /* Keep us alive until the job is done! */
+ NS_ADDREF_THIS ();
+ gtk_print_job_send (mJob,
+ (GtkPrintJobCompleteFunc) JobCompletedCallback,
+ this,
+ (GDestroyNotify) ReleaseSession);
+}
+
+void
+GeckoPrintSession::JobStatusChanged ()
+{
+ NS_ENSURE_TRUE (mProgressDialog, );
+
+ LOG ("print session %p status changed %d\n", this, gtk_print_job_get_status (mJob));
+
+ /* FIXME: are any other status codes relevant info for the user? */
+ if (gtk_print_job_get_status (mJob) == GTK_PRINT_STATUS_SENDING_DATA) {
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (mProgressBar), 0.75);
+ /* FIXME text! */
+ SetProgressText (_("Spooling..."));
+ }
+}
+
+void
+GeckoPrintSession::JobError (const char *aErrorMessage)
+{
+ LOG ("print job error: %s", aErrorMessage);
+
+ /* FIXME better text */
+ GtkWidget *dialog = gtk_message_dialog_new (NULL,
+ GtkDialogFlags (0),
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("Print error"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", aErrorMessage);
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+
+ gtk_widget_show (dialog);
+}
+
+void
+GeckoPrintSession::JobDone ()
+{
+ NS_ENSURE_TRUE (mProgressDialog, );
+
+ mDone = PR_TRUE;
+
+ gtk_widget_hide (mProgressDialog);
+
+ DestroyJob ();
+}
+
+void
+GeckoPrintSession::DestroyJob ()
+{
+ if (!mJob) return;
+
+ g_signal_handlers_disconnect_by_func (mJob, (void*) JobStatusChangedCallback, this);
+ g_object_unref (mJob);
+ mJob = NULL;
+}
+
+void
+GeckoPrintSession::LaunchJobOnIdle ()
+{
+ NS_ASSERTION (!mStartPrintIdleID, "Already started printing!");
+
+ /* Don't send the job to the printer if the user cancelled the print */
+ if (mCancelled) return;
+
+ /* Keep us alive until the idle handler runs! */
+ NS_ADDREF_THIS ();
+ mStartPrintIdleID = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+ (GSourceFunc) StartPrintIdleCallback,
+ this,
+ (GDestroyNotify) ReleaseSession);
+}
+
+/* XPCOM interfaces */
+
+NS_IMPL_THREADSAFE_ISUPPORTS5 (GeckoPrintSession,
+ nsIPrintSession,
+ nsIWebProgressListener,
+ nsIPrintProgress,
+ nsIPrintProgressParams,
+ nsISupportsWeakReference)
+
+/* nsIPrintSession implementation */
+
+/* nsIWebProgressListener implementation */
+
+/* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */
+NS_IMETHODIMP
+GeckoPrintSession::OnStateChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRUint32 aStateFlags,
+ nsresult aStatus)
+{
+ if (NS_SUCCEEDED (aStatus) &&
+ aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) {
+ if (aStateFlags & nsIWebProgressListener::STATE_START) {
+ /* Printing starts now */
+ SetProgress (0, 0);
+ } else if ((aStateFlags & nsIWebProgressListener::STATE_STOP)) {
+ /* Printing done, upload to printer */
+ LaunchJobOnIdle ();
+ }
+ }
+
+ return NS_OK;
+}
+
+/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
+NS_IMETHODIMP
+GeckoPrintSession::OnProgressChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRInt32 aCurSelfProgress,
+ PRInt32 aMaxSelfProgress,
+ PRInt32 aCurTotalProgress,
+ PRInt32 aMaxTotalProgress)
+{
+ SetProgress (aCurTotalProgress, aMaxTotalProgress);
+
+ return NS_OK;
+}
+
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI aLocation); */
+NS_IMETHODIMP
+GeckoPrintSession::OnLocationChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ nsIURI *aLocation)
+{
+ NS_ASSERTION (0, "OnLocationChange reached!");
+ return NS_OK;
+}
+
+/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
+NS_IMETHODIMP
+GeckoPrintSession::OnStatusChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ nsresult aStatus,
+ const PRUnichar *aMessage)
+{
+ NS_ASSERTION (0, "OnStatusChange reached!");
+ return NS_OK;
+}
+
+/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aState); */
+NS_IMETHODIMP
+GeckoPrintSession::OnSecurityChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRUint32 aState)
+{
+ NS_ASSERTION (0, "OnSecurityChange reached!");
+ return NS_OK;
+}
+
+/* nsIPrintProgress implementation */
+
+/* void openProgressDialog (in nsIDOMWindowInternal parent, in string dialogURL, in nsISupports parameters, in nsIObserver openDialogObserver, out boolean notifyOnOpen); */
+NS_IMETHODIMP
+GeckoPrintSession::OpenProgressDialog (nsIDOMWindowInternal *aParent,
+ const char *aDialogURL,
+ nsISupports *aParameters,
+ nsIObserver *aOpenDialogObserver,
+ PRBool *_notifyOnOpen)
+{
+ NS_ENSURE_STATE (!mProgressDialog);
+
+ nsCOMPtr<nsIDOMWindow> domWindow (do_QueryInterface (aParent));
+ GtkWidget *parent = EphyUtils::FindGtkParent (domWindow);
+
+ GtkWidget *vbox, *hbox, *image;
+
+ mProgressDialog = gtk_dialog_new ();
+ GtkDialog *dialog = GTK_DIALOG (mProgressDialog);
+
+ gtk_dialog_add_button (dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+
+ g_signal_connect (dialog, "delete-event",
+ G_CALLBACK (ProgressDeleteCallback), NULL);
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (ProgressResponseCallback), this);
+
+ /* FIXME do we need transient? initially on top should suffice */
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ GTK_WINDOW (parent));
+
+ gtk_dialog_set_has_separator (dialog, FALSE);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+ gtk_box_set_spacing (GTK_BOX (dialog->vbox), 14); /* 2 * 5 + 14 = 24 */
+ gtk_box_set_spacing (GTK_BOX (dialog->action_area), 5);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+ gtk_container_add (GTK_CONTAINER (dialog->vbox), hbox);
+
+ image = gtk_image_new_from_stock (GTK_STOCK_PRINT, GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+
+ mTitleLabel = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (mTitleLabel), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (mTitleLabel), 0.0, 0.0);
+ gtk_box_pack_start (GTK_BOX (vbox), mTitleLabel, FALSE, FALSE, 0);
+
+ mProgressBar = gtk_progress_bar_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), mProgressBar, FALSE, FALSE, 0);
+
+ gtk_widget_show_all (hbox);
+ gtk_window_present (GTK_WINDOW (dialog));
+
+ *_notifyOnOpen = PR_FALSE;
+
+ return NS_OK;
+}
+
+/* void closeProgressDialog (in boolean forceClose); */
+NS_IMETHODIMP
+GeckoPrintSession::CloseProgressDialog (PRBool forceClose)
+{
+ return NS_OK;
+}
+
+/* void registerListener (in nsIWebProgressListener listener); */
+NS_IMETHODIMP
+GeckoPrintSession::RegisterListener (nsIWebProgressListener *listener)
+{
+ return NS_OK;
+}
+
+/* void unregisterListener (in nsIWebProgressListener listener); */
+NS_IMETHODIMP
+GeckoPrintSession::UnregisterListener (nsIWebProgressListener *listener)
+{
+ return NS_OK;
+}
+
+/* void doneIniting (); */
+NS_IMETHODIMP
+GeckoPrintSession::DoneIniting()
+{
+ return NS_OK;
+}
+
+/* nsIPrompt getPrompter (); */
+NS_IMETHODIMP
+GeckoPrintSession::GetPrompter (nsIPrompt **_retval)
+{
+ g_return_val_if_reached (NS_ERROR_NOT_IMPLEMENTED);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute boolean processCanceledByUser; */
+NS_IMETHODIMP
+GeckoPrintSession::GetProcessCanceledByUser (PRBool *aProcessCanceledByUser)
+{
+ *aProcessCanceledByUser = mCancelled;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GeckoPrintSession::SetProcessCanceledByUser (PRBool aProcessCanceledByUser)
+{
+ mCancelled = aProcessCanceledByUser;
+ if (mPrintSettings) {
+ mPrintSettings->SetIsCancelled (aProcessCanceledByUser);
+ }
+
+ return NS_OK;
+}
+
+/* nsIPrintProgressParams implementation */
+
+/* attribute wstring docTitle; */
+NS_IMETHODIMP
+GeckoPrintSession::GetDocTitle (PRUnichar * *aDocTitle)
+{
+ g_return_val_if_reached (NS_ERROR_NOT_IMPLEMENTED);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+GeckoPrintSession::SetDocTitle (const PRUnichar * aDocTitle)
+{
+ NS_ENSURE_STATE (mProgressDialog);
+
+ char *converted = EphyUtils::ConvertUTF16toUTF8 (aDocTitle, MAX_STRING_LENGTH);
+ if (converted) {
+ mTitle.Assign (converted);
+
+ char *title = g_strdup_printf (_("Printing “%s”"), converted);
+ gtk_window_set_title (GTK_WINDOW (mProgressDialog), title);
+ gtk_label_set_text (GTK_LABEL (mTitleLabel), title);
+ g_free (converted);
+ g_free (title);
+ }
+ return NS_OK;
+}
+
+/* attribute wstring docURL; */
+NS_IMETHODIMP
+GeckoPrintSession::GetDocURL (PRUnichar * *aDocURL)
+{
+ g_return_val_if_reached (NS_ERROR_NOT_IMPLEMENTED);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+GeckoPrintSession::SetDocURL (const PRUnichar * aDocURL)
+{
+#if 0
+ NS_ENSURE_STATE (mJob);
+
+ char *converted = EphyUtils::ConvertUTF16toUTF8 (aDocTitle, MAX_STRING_LENGTH);
+ if (converted) {
+ g_free (converted);
+ }
+#endif
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/GeckoPrintSession.h b/embed/xulrunner/embed/GeckoPrintSession.h
new file mode 100644
index 000000000..027f01e23
--- /dev/null
+++ b/embed/xulrunner/embed/GeckoPrintSession.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef GECKO_PRINT_SESSION_H
+#define GECKO_PRINT_SESSION_H
+
+#include <nsCOMPtr.h>
+#include <nsIPrintSession.h>
+#include <nsIWebProgressListener.h>
+#include <nsIPrintProgress.h>
+#include <nsIPrintProgressParams.h>
+#include <nsWeakReference.h>
+
+#include <gtk/gtkwidget.h>
+#include <gtk/gtkprintjob.h>
+#include <gtk/gtkprinter.h>
+#include <gtk/gtkprintjob.h>
+
+class nsIPrintSettings;
+class nsIDOMWindow;
+
+/* 0940c973-97e7-476f-a612-4ed9473a0b36 */
+#define GECKO_PRINT_SESSION_IID \
+{ 0x0940c973, 0x97e7, 0x476f, \
+ { 0xa6, 0x12, 0x4e, 0xd9, 0x47, 0x3a, 0x0b, 0x36 } }
+
+#define GECKO_PRINT_SESSION_CLASSNAME "Gecko Print Session"
+
+class GeckoPrintSession : public nsIPrintSession,
+ public nsIPrintProgress,
+ public nsIPrintProgressParams,
+ public nsSupportsWeakReference
+{
+ public:
+ GeckoPrintSession();
+ virtual ~GeckoPrintSession();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPRINTSESSION
+ NS_DECL_NSIWEBPROGRESSLISTENER
+ NS_DECL_NSIPRINTPROGRESS
+ NS_DECL_NSIPRINTPROGRESSPARAMS
+
+ nsresult SetSettings (nsIPrintSettings *, GtkPrintSettings*, GtkPageSetup*, GtkPrinter*);
+ void GetSourceFile (nsACString&);
+
+ static GeckoPrintSession *FromSettings (nsIPrintSettings *);
+
+ void Cancel ();
+ void StartPrinting ();
+ void JobStatusChanged ();
+ void JobDone ();
+ void JobError (const char *);
+
+ private:
+ nsCOMPtr<nsIPrintSettings> mPrintSettings;
+ GtkPrintSettings *mSettings;
+ GtkPageSetup *mPageSetup;
+ GtkPrinter *mPrinter;
+ GtkPrintJob *mJob;
+ GtkWidget *mProgressDialog;
+ GtkWidget *mTitleLabel;
+ GtkWidget *mProgressBar;
+ nsCString mSourceFile;
+ nsCString mTitle;
+ guint mStartPrintIdleID;
+ PRPackedBool mSourceFileIsTemp;
+ PRPackedBool mDone;
+ PRPackedBool mCancelled;
+
+ void SetProgress (PRInt32, PRInt32);
+ void SetProgressText (const char *);
+ void LaunchJobOnIdle ();
+ void DestroyJob ();
+};
+
+#endif /* GECKO_PRINT_SESSION_H */
diff --git a/embed/xulrunner/embed/GeckoSpellCheckEngine.cpp b/embed/xulrunner/embed/GeckoSpellCheckEngine.cpp
new file mode 100644
index 000000000..59ab5df2d
--- /dev/null
+++ b/embed/xulrunner/embed/GeckoSpellCheckEngine.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+//#include <bonobo.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <nsStringAPI.h>
+
+#include <mozIPersonalDictionary.h>
+#include <nsMemory.h>
+
+#include "ephy-debug.h"
+
+#include "GeckoSpellCheckEngine.h"
+
+#ifndef HAVE_GECKO_1_9
+#define ToNewUnicode NS_StringCloneData
+#endif
+
+GeckoSpellCheckEngine::GeckoSpellCheckEngine ()
+{
+ LOG ("GeckoSpellCheckEngine ctor [%p]", (void*) this);
+ mSpeller = ephy_spell_check_get_default ();
+}
+
+GeckoSpellCheckEngine::~GeckoSpellCheckEngine ()
+{
+ LOG ("GeckoSpellCheckEngine dtor [%p]", (void*) this);
+ g_object_unref (mSpeller);
+}
+
+NS_IMPL_ISUPPORTS1 (GeckoSpellCheckEngine,
+ mozISpellCheckingEngine)
+
+/* nsISpellCheckEngine implementation */
+
+/* attribute wstring dictionary; */
+NS_IMETHODIMP GeckoSpellCheckEngine::GetDictionary (PRUnichar * *aDictionary)
+{
+ /* Gets the identifier of the current dictionary */
+ char *code = ephy_spell_check_get_language (mSpeller);
+ if (!code) {
+ return NS_ERROR_FAILURE;
+ }
+
+ *aDictionary = ToNewUnicode (NS_ConvertUTF8toUTF16 (code));
+ g_free (code);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP GeckoSpellCheckEngine::SetDictionary (const PRUnichar * aDictionary)
+{
+ return NS_OK;
+}
+
+/* readonly attribute wstring language; */
+NS_IMETHODIMP GeckoSpellCheckEngine::GetLanguage (PRUnichar * *aLanguage)
+{
+ /* Gets the identifier of the current dictionary */
+ char *code = ephy_spell_check_get_language (mSpeller);
+ if (!code) {
+ return NS_ERROR_FAILURE;
+ }
+
+ *aLanguage = ToNewUnicode (NS_ConvertUTF8toUTF16 (code));
+ g_free (code);
+
+ return NS_OK;
+}
+
+/* readonly attribute boolean providesPersonalDictionary; */
+NS_IMETHODIMP GeckoSpellCheckEngine::GetProvidesPersonalDictionary (PRBool *aProvidesPersonalDictionary)
+{
+ *aProvidesPersonalDictionary = PR_FALSE;
+ return NS_OK;
+}
+
+/* readonly attribute boolean providesWordUtils; */
+NS_IMETHODIMP GeckoSpellCheckEngine::GetProvidesWordUtils (PRBool *aProvidesWordUtils)
+{
+ *aProvidesWordUtils = PR_FALSE;
+ return NS_OK;
+}
+
+/* readonly attribute wstring name; */
+NS_IMETHODIMP GeckoSpellCheckEngine::GetName (PRUnichar * *aName)
+{
+ /* It's fine to leave this unimplemented */
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* readonly attribute wstring copyright; */
+NS_IMETHODIMP GeckoSpellCheckEngine::GetCopyright (PRUnichar * *aCopyright)
+{
+ /* It's fine to leave this unimplemented */
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute mozIPersonalDictionary personalDictionary; */
+NS_IMETHODIMP GeckoSpellCheckEngine::GetPersonalDictionary (mozIPersonalDictionary * *aPersonalDictionary)
+{
+ NS_IF_ADDREF (*aPersonalDictionary = mPersonalDictionary);
+ return NS_OK;
+}
+
+NS_IMETHODIMP GeckoSpellCheckEngine::SetPersonalDictionary (mozIPersonalDictionary * aPersonalDictionary)
+{
+ mPersonalDictionary = aPersonalDictionary;
+ return NS_OK;
+}
+
+/* void getDictionaryList ([array, size_is (count)] out wstring dictionaries, out PRUint32 count); */
+NS_IMETHODIMP
+GeckoSpellCheckEngine::GetDictionaryList (PRUnichar ***_dictionaries,
+ PRUint32 *_count)
+{
+ *_count = 1;
+ *_dictionaries = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *)); // only one entry
+ *_dictionaries[0] = ToNewUnicode (NS_LITERAL_STRING ("en"));
+ return NS_OK;
+}
+
+/* boolean check (in wstring word); */
+NS_IMETHODIMP GeckoSpellCheckEngine::Check (const PRUnichar *word,
+ PRBool *_retval)
+{
+ NS_ENSURE_STATE (mSpeller);
+ NS_ENSURE_ARG (word);
+
+ NS_ConvertUTF16toUTF8 converted (word);
+
+ gboolean correct = FALSE;
+ if (!ephy_spell_check_check_word (mSpeller,
+ converted.get (),
+ converted.Length (),
+ &correct))
+ return NS_ERROR_FAILURE;
+
+ *_retval = correct != FALSE;
+
+ return NS_OK;
+}
+
+/* void suggest (in wstring word, [array, size_is (count)] out wstring suggestions, out PRUint32 count); */
+NS_IMETHODIMP GeckoSpellCheckEngine::Suggest (const PRUnichar *word,
+ PRUnichar ***_suggestions,
+ PRUint32 *_count)
+{
+#if 0
+ NS_ENSURE_STATE (mSpeller);
+ NS_ENSURE_ARG (word);
+
+ NS_ConvertUTF16toUTF8 converted (word);
+
+ gsize count;
+ char **suggestions = ephy_spell_check_get_suggestions (mSpeller,
+ converted.get (),
+ converted.Length (),
+ &count);
+
+ *_count = count;
+ *_suggestions = nsnull;
+
+ PRUnichar **array = nsnull;
+ if (count > 0) {
+ NS_ASSERTION (suggestions, "Count > 0 but suggestions are NULL?");
+ array = (PRUnichar **) nsMemory::Alloc (count * sizeof (PRUnichar *));
+ if (array) {
+ *_suggestions = array;
+
+ for (gsize i = 0; i < count; ++i) {
+ NS_ConvertUTF8toUTF16 sugg (suggestions[i]);
+ array[i] = ToNewUnicode (sugg);
+ }
+ }
+
+ ephy_spell_check_free_suggestions (mSpeller, suggestions);
+ }
+
+ return array ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+#endif
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/embed/xulrunner/embed/GeckoSpellCheckEngine.h b/embed/xulrunner/embed/GeckoSpellCheckEngine.h
new file mode 100644
index 000000000..b70f6c970
--- /dev/null
+++ b/embed/xulrunner/embed/GeckoSpellCheckEngine.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef GECKO_SPELL_CHECK_ENGINE_H
+#define GECKO_SPELL_CHECK_ENGINE_H
+
+#include <nsCOMPtr.h>
+#include <mozISpellCheckingEngine.h>
+
+#include "ephy-spell-check.h"
+
+class mozIPersonalDictionary;
+
+/* 26948b8b-d136-4a78-a9c5-3a145812b649 */
+#define GECKO_SPELL_CHECK_ENGINE_IID \
+{ 0x26948b8b, 0xd136, 0x4a78, { 0xa9, 0xc5, 0x3a, 0x14, 0x58, 0x12, 0xb6, 0x49 } }
+
+#define GECKO_SPELL_CHECK_ENGINE_CONTRACTID "@mozilla.org/spellchecker/myspell;1"
+#define GECKO_SPELL_CHECK_ENGINE_CLASSNAME "Gecko Print Settings"
+
+class GeckoSpellCheckEngine : public mozISpellCheckingEngine
+{
+ public:
+ GeckoSpellCheckEngine();
+ virtual ~GeckoSpellCheckEngine();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_MOZISPELLCHECKINGENGINE
+
+ private:
+ nsCOMPtr<mozIPersonalDictionary> mPersonalDictionary;
+ EphySpellCheck *mSpeller;
+};
+
+#endif /* GECKO_SPELL_CHECK_ENGINE_H */
diff --git a/embed/xulrunner/embed/GlobalHistory.cpp b/embed/xulrunner/embed/GlobalHistory.cpp
new file mode 100644
index 000000000..efcda79f9
--- /dev/null
+++ b/embed/xulrunner/embed/GlobalHistory.cpp
@@ -0,0 +1,225 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright © 2001, 2004 Philip Langdale
+ * Copyright © 2004 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <nsStringAPI.h>
+
+#include <nsIURI.h>
+
+#include "ephy-embed-shell.h"
+
+#include "GlobalHistory.h"
+
+
+#define MAX_TITLE_LENGTH 2048
+#define MAX_URL_LENGTH 16384
+
+#ifdef HAVE_NSIGLOBALHISTORY3_H
+NS_IMPL_ISUPPORTS2 (MozGlobalHistory, nsIGlobalHistory2, nsIGlobalHistory3)
+#else
+NS_IMPL_ISUPPORTS1 (MozGlobalHistory, nsIGlobalHistory2)
+#endif /* HAVE_NSIGLOBALHISTORY3_H */
+
+MozGlobalHistory::MozGlobalHistory ()
+{
+ mGlobalHistory = EPHY_HISTORY (ephy_embed_shell_get_global_history (embed_shell));
+
+ mHistoryListener = new EphyHistoryListener ();
+ mHistoryListener->Init (mGlobalHistory);
+}
+
+MozGlobalHistory::~MozGlobalHistory ()
+{
+}
+
+/* void addURI (in nsIURI aURI, in boolean aRedirect, in boolean aToplevel, in nsIURI aReferrer); */
+NS_IMETHODIMP MozGlobalHistory::AddURI(nsIURI *aURI,
+ PRBool aRedirect,
+ PRBool aToplevel,
+ nsIURI *aReferrer)
+{
+ nsresult rv;
+
+ NS_ENSURE_ARG (aURI);
+
+ // filter out unwanted URIs such as chrome: etc
+ // The model is really if we don't know differently then add which basically
+ // means we are suppose to try all the things we know not to allow in and
+ // then if we don't bail go on and allow it in. But here lets compare
+ // against the most common case we know to allow in and go on and say yes
+ // to it.
+
+ PRBool isHTTP = PR_FALSE, isHTTPS = PR_FALSE;
+ rv = aURI->SchemeIs("http", &isHTTP);
+ rv |= aURI->SchemeIs("https", &isHTTPS);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ if (!isHTTP && !isHTTPS)
+ {
+ static const char *schemes[] = { "javascript",
+ "data",
+ "about",
+ "chrome",
+ "resource",
+ "view-source" };
+
+ for (PRUint32 i = 0; i < G_N_ELEMENTS (schemes); ++i)
+ {
+ PRBool result = PR_FALSE;
+ if (NS_SUCCEEDED (aURI->SchemeIs (schemes[i], &result)) && result)
+ {
+ return NS_OK;
+ }
+ }
+ }
+
+ nsCString spec;
+ rv = aURI->GetSpec(spec);
+ NS_ENSURE_TRUE (NS_SUCCEEDED(rv) && spec.Length(), rv);
+
+ if (spec.Length () > MAX_URL_LENGTH) return NS_OK;
+
+ ephy_history_add_page (mGlobalHistory, spec.get(), aRedirect, aToplevel);
+
+ return NS_OK;
+}
+
+/* boolean isVisited (in nsIURI aURI); */
+NS_IMETHODIMP MozGlobalHistory::IsVisited(nsIURI *aURI,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG (aURI);
+
+ *_retval = PR_FALSE;
+
+ nsCString spec;
+ aURI->GetSpec(spec);
+
+ if (spec.Length () > MAX_URL_LENGTH) return NS_OK;
+
+ *_retval = ephy_history_is_page_visited (mGlobalHistory, spec.get());
+
+ return NS_OK;
+}
+
+/* void setPageTitle (in nsIURI aURI, in AString aTitle); */
+NS_IMETHODIMP MozGlobalHistory::SetPageTitle(nsIURI *aURI,
+ const nsAString & aTitle)
+{
+ NS_ENSURE_ARG (aURI);
+
+ nsCString spec;
+ aURI->GetSpec(spec);
+
+ if (spec.Length () > MAX_URL_LENGTH) return NS_OK;
+
+ nsString uTitle (aTitle);
+
+ /* This depends on the assumption that
+ * typeof(PRUnichar) == typeof (gunichar2) == uint16,
+ * which should be pretty safe.
+ */
+ glong n_read = 0, n_written = 0;
+ char *converted = g_utf16_to_utf8 ((gunichar2*) uTitle.get(), MAX_TITLE_LENGTH,
+ &n_read, &n_written, NULL);
+ /* FIXME loop from the end while !g_unichar_isspace (char)? */
+ if (converted == NULL) return NS_OK;
+
+ ephy_history_set_page_title (mGlobalHistory, spec.get(), converted);
+
+ g_free (converted);
+
+ return NS_OK;
+}
+
+#ifdef HAVE_NSIGLOBALHISTORY3_H
+
+#ifdef HAVE_GECKO_1_9
+
+/* unsigned long getURIGeckoFlags(in nsIURI aURI); */
+NS_IMETHODIMP
+MozGlobalHistory::GetURIGeckoFlags(nsIURI *aURI,
+ PRUint32* aFlags)
+{
+ *aFlags = 0;
+
+ nsCString spec;
+ aURI->GetSpec(spec);
+
+ if (spec.Length () > MAX_URL_LENGTH) return NS_OK;
+
+ EphyNode *page = ephy_history_get_page (mGlobalHistory, spec.get());
+
+ GValue value = { 0, };
+ if (page != NULL &&
+ ephy_node_get_property (page, EPHY_NODE_PAGE_PROP_GECKO_FLAGS, &value))
+ {
+ *aFlags = (PRUint32) (gulong) g_value_get_long (&value);
+ g_value_unset (&value);
+
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+/* void setURIGeckoFlags(in nsIURI aURI, in unsigned long aFlags); */
+NS_IMETHODIMP
+MozGlobalHistory::SetURIGeckoFlags(nsIURI *aURI,
+ PRUint32 aFlags)
+{
+ nsCString spec;
+ aURI->GetSpec(spec);
+
+ if (spec.Length () > MAX_URL_LENGTH) return NS_OK;
+
+ EphyNode *page = ephy_history_get_page (mGlobalHistory, spec.get());
+ if (page != NULL)
+ {
+ ephy_node_set_property_long (page,
+ EPHY_NODE_PAGE_PROP_GECKO_FLAGS,
+ aFlags);
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+#endif /* HAVE_GECKO_1_9 */
+
+/* void addDocumentRedirect (in nsIChannel
+ aOldChannel,
+ in nsIChannel aNewChannel,
+ in PRInt32 aFlags,
+ in boolean aTopLevel); */
+NS_IMETHODIMP
+MozGlobalHistory::AddDocumentRedirect(nsIChannel *aOldChannel,
+ nsIChannel *aNewChannel,
+ PRInt32 aFlags,
+ PRBool aTopLevel)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#endif /* HAVE_NSIGLOBALHISTORY3_H */
diff --git a/embed/xulrunner/embed/GlobalHistory.h b/embed/xulrunner/embed/GlobalHistory.h
new file mode 100644
index 000000000..8397874a0
--- /dev/null
+++ b/embed/xulrunner/embed/GlobalHistory.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2001, 2004 Philip Langdale
+ * Copyright © 2004 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_GLOBAL_HISTORY_H
+#define EPHY_GLOBAL_HISTORY_H
+
+#ifdef HAVE_NSIGLOBALHISTORY3_H
+#include <nsIGlobalHistory3.h>
+#else
+#include <nsIGlobalHistory2.h>
+#endif /* HAVE_NSIGLOBALHISTORY3_H */
+
+#include <nsAutoPtr.h>
+#include <nsCOMPtr.h>
+
+#include "ephy-history.h"
+
+#include "EphyHistoryListener.h"
+
+#define EPHY_GLOBALHISTORY_CLASSNAME "Epiphany Global History Implementation"
+
+#define EPHY_GLOBALHISTORY_CID \
+{ 0xbe0c42c1, \
+ 0x39d4, \
+ 0x4271, \
+ { 0xb7, 0x9e, 0xf7, 0xaa, 0x49, 0xeb, 0x6a, 0x15} \
+}
+
+#ifdef HAVE_NSIGLOBALHISTORY3_H
+class MozGlobalHistory: public nsIGlobalHistory3
+#else
+class MozGlobalHistory: public nsIGlobalHistory2
+#endif /* HAVE_NSIGLOBALHISTORY3_H */
+{
+ public:
+ MozGlobalHistory ();
+ virtual ~MozGlobalHistory();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIGLOBALHISTORY2
+#ifdef HAVE_NSIGLOBALHISTORY3_H
+ NS_DECL_NSIGLOBALHISTORY3
+#endif /* HAVE_NSIGLOBALHISTORY3_H */
+
+ private:
+ EphyHistory *mGlobalHistory;
+ nsRefPtr<EphyHistoryListener> mHistoryListener;
+};
+
+#endif /* EPHY_GLOBAL_HISTORY_H */
diff --git a/embed/xulrunner/embed/GtkNSSClientAuthDialogs.cpp b/embed/xulrunner/embed/GtkNSSClientAuthDialogs.cpp
new file mode 100644
index 000000000..410827166
--- /dev/null
+++ b/embed/xulrunner/embed/GtkNSSClientAuthDialogs.cpp
@@ -0,0 +1,284 @@
+/*
+ * GtkNSSClientAuthDialogs.cpp
+ *
+ * Copyright © 2003 Crispin Flowerday <gnome@flowerday.cx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkcellrenderer.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtkcombobox.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkexpander.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkmenuitem.h>
+#include <gtk/gtkoptionmenu.h>
+#include <gtk/gtkprogressbar.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtktextbuffer.h>
+#include <gtk/gtktextview.h>
+#include <gtk/gtktogglebutton.h>
+#include <gtk/gtktreemodel.h>
+#include <gtk/gtkvbox.h>
+
+#include <nsStringAPI.h>
+
+#include <nsIDOMWindow.h>
+#include <nsIInterfaceRequestor.h>
+#include <nsIInterfaceRequestorUtils.h>
+#include <nsIServiceManager.h>
+
+#include "ephy-debug.h"
+#include "ephy-gui.h"
+#include "ephy-state.h"
+#include "ephy-stock-icons.h"
+
+#include "AutoJSContextStack.h"
+#include "AutoWindowModalState.h"
+#include "EphyUtils.h"
+
+#include "GtkNSSClientAuthDialogs.h"
+
+GtkNSSClientAuthDialogs::GtkNSSClientAuthDialogs()
+{
+ LOG ("GtkNSSClientAuthDialogs ctor (%p)", this);
+}
+
+
+GtkNSSClientAuthDialogs::~GtkNSSClientAuthDialogs()
+{
+ LOG ("GtkNSSClientAuthDialogs dtor (%p)", this);
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1 (GtkNSSClientAuthDialogs,
+ nsIClientAuthDialogs)
+
+/**
+ * Indent a widget according the HIG
+ *
+ * @returns: The new indented widget
+ */
+static GtkWidget*
+higgy_indent_widget (GtkWidget *widget)
+{
+ GtkWidget *hbox;
+ GtkWidget *label;
+
+ hbox = gtk_hbox_new (FALSE, 6);
+
+ label = gtk_label_new ("");
+ gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, TRUE, 6);
+ gtk_widget_show (label);
+
+ gtk_box_pack_start (GTK_BOX(hbox), widget, TRUE, TRUE, 0);
+
+ return hbox;
+}
+
+static void
+combo_changed_cb (GtkComboBox *combo, GtkTextView *textview)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTextBuffer *buffer;
+ int index;
+
+ model = gtk_combo_box_get_model (combo);
+ index = gtk_combo_box_get_active (combo);
+ buffer = gtk_text_view_get_buffer (textview);
+
+ if (gtk_tree_model_iter_nth_child (model, &iter, NULL, index))
+ {
+ char *text;
+
+ gtk_tree_model_get (model, &iter, 1, &text, -1);
+
+ gtk_text_buffer_set_text (buffer, text, -1);
+
+ g_free (text);
+ }
+ else
+ {
+ gtk_text_buffer_set_text (buffer, "", -1);
+ }
+}
+
+NS_IMETHODIMP
+GtkNSSClientAuthDialogs::ChooseCertificate (nsIInterfaceRequestor *ctx,
+ const PRUnichar *cn,
+ const PRUnichar *organization,
+ const PRUnichar *issuer,
+ const PRUnichar **certNickList,
+ const PRUnichar **certDetailsList,
+ PRUint32 count, PRInt32 *selectedIndex,
+ PRBool *canceled)
+{
+ GtkWidget *dialog, *label, *vbox, *textview;
+ GtkWidget *details, *expander, *hbox, *image;
+ GtkWidget *combo;
+ GtkListStore *store;
+ GtkTreeIter iter;
+ GtkCellRenderer *renderer;
+ char *msg, *markup_text;
+ PRUint32 i;
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
+ GtkWindow *gparent = GTK_WINDOW (EphyUtils::FindGtkParent (parent));
+
+ AutoWindowModalState modalState (parent);
+
+ dialog = gtk_dialog_new_with_buttons ("",
+ GTK_WINDOW (gparent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ _("_Select Certificate"),
+ GTK_RESPONSE_OK,
+ (char *) NULL);
+
+ if (gparent)
+ {
+ gtk_window_group_add_window (ephy_gui_ensure_window_group (gparent),
+ GTK_WINDOW (dialog));
+ }
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+ gtk_box_set_spacing (GTK_BOX(GTK_DIALOG (dialog)->vbox), 14); /* 24 = 2 * 5 + 14 */
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
+ gtk_widget_show (hbox);
+
+ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
+ GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+ gtk_widget_show (image);
+
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+ gtk_widget_show (vbox);
+
+ label = gtk_label_new (NULL);
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+ gtk_widget_show (label);
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+ msg = g_markup_printf_escaped (_("Choose a certificate to present as identification to “%s”."),
+ NS_ConvertUTF16toUTF8 (cn).get());
+ markup_text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
+ _("Select a certificate to identify yourself."),
+ msg);
+ gtk_label_set_markup (GTK_LABEL (label), markup_text);
+ g_free (msg);
+ g_free (markup_text);
+
+ /* Create and populate the combo */
+ store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+ for (i = 0; i < count; i++)
+ {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ 0, NS_ConvertUTF16toUTF8 (certNickList[i]).get(),
+ 1, NS_ConvertUTF16toUTF8 (certDetailsList[i]).get(),
+ -1);
+ }
+
+ combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
+ "text", 0,
+ (char *) NULL);
+
+ gtk_widget_show (combo);
+ gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, TRUE, 0);
+
+ expander = gtk_expander_new_with_mnemonic (_("Certificate _Details"));
+ ephy_state_add_expander (GTK_WIDGET (expander), "client-auth-dialog-expander", FALSE);
+
+ gtk_widget_show (expander);
+ gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), expander, FALSE, FALSE, 0);
+
+ /* Create the text box */
+ textview = gtk_text_view_new ();
+ gtk_text_view_set_editable (GTK_TEXT_VIEW (textview), FALSE);
+ gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (textview), FALSE);
+ gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (textview), GTK_WRAP_WORD);
+ gtk_widget_set_size_request (GTK_WIDGET (textview), -1, 100);
+ gtk_widget_show (textview);
+
+ details = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (details), GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (details), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (details), textview);
+ gtk_widget_show (details);
+
+ details = higgy_indent_widget (details);
+ gtk_container_set_border_width (GTK_CONTAINER (details), 5);
+ gtk_widget_show (details);
+
+ gtk_container_add (GTK_CONTAINER (expander), details);
+
+ g_signal_connect (G_OBJECT (combo), "changed",
+ G_CALLBACK (combo_changed_cb),
+ textview);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+
+ /* run the dialog */
+ int res = gtk_dialog_run (GTK_DIALOG (dialog));
+ if (res == GTK_RESPONSE_OK)
+ {
+ *canceled = PR_FALSE;
+ *selectedIndex = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+ }
+ else
+ {
+ *canceled = PR_TRUE;
+ }
+
+ gtk_widget_destroy (dialog);
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/GtkNSSClientAuthDialogs.h b/embed/xulrunner/embed/GtkNSSClientAuthDialogs.h
new file mode 100644
index 000000000..0aa582700
--- /dev/null
+++ b/embed/xulrunner/embed/GtkNSSClientAuthDialogs.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2003 Crispin Flowerday <gnome@flowerday.cx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * $Id$
+ */
+
+#ifndef GTKNSSCLIENTAUTHDIALOGS_H
+#define GTKNSSCLIENTAUTHDIALOGS_H 1
+
+#include <nsIClientAuthDialogs.h>
+
+// 55b3837e-dbde-4c24-9247-f328e3012485
+#define GTK_NSSCLIENTAUTHDIALOGS_CID \
+ {0x55b3837e, 0xdbde, 0x4c24, {0x92, 0x47, 0xf3, 0x28, 0xe3, 0x01, 0x24, 0x85}}
+
+#define GTK_NSSCLIENTAUTHDIALOGS_CLASSNAME "Gtk NSS Client Auth Dialogs"
+
+class GtkNSSClientAuthDialogs
+: public nsIClientAuthDialogs
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICLIENTAUTHDIALOGS
+
+ GtkNSSClientAuthDialogs();
+ virtual ~GtkNSSClientAuthDialogs();
+};
+
+
+#endif /* GTKNSSCLIENTAUTHDIALOGS_H */
diff --git a/embed/xulrunner/embed/GtkNSSDialogs.cpp b/embed/xulrunner/embed/GtkNSSDialogs.cpp
new file mode 100644
index 000000000..25b99d141
--- /dev/null
+++ b/embed/xulrunner/embed/GtkNSSDialogs.cpp
@@ -0,0 +1,1694 @@
+/*
+ * Copyright © 2003 Crispin Flowerday <gnome@flowerday.cx>
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+/*
+ * This file provides Gtk implementations of the mozilla Certificate dialogs
+ * such as the ones displayed when connecting to a site with a self-signed
+ * or expired certificate.
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <time.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtkalignment.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkeditable.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkprogressbar.h>
+#include <gtk/gtksizegroup.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtktable.h>
+#include <gtk/gtktextbuffer.h>
+#include <gtk/gtktextview.h>
+#include <gtk/gtktogglebutton.h>
+#include <gtk/gtktreeselection.h>
+#include <gtk/gtktreestore.h>
+#include <gtk/gtktreeview.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkcombobox.h>
+#include <gconf/gconf-client.h>
+#include <glade/glade-xml.h>
+
+#include <nsStringAPI.h>
+
+#include <nsCOMPtr.h>
+#include <nsIArray.h>
+#include <nsIASN1Object.h>
+#include <nsIASN1Sequence.h>
+#include <nsICRLInfo.h>
+#include <nsIDOMWindow.h>
+#include <nsIInterfaceRequestor.h>
+#include <nsIInterfaceRequestorUtils.h>
+#include <nsIPKCS11ModuleDB.h>
+#include <nsIPKCS11Slot.h>
+#include <nsIPK11Token.h>
+#include <nsIPK11TokenDB.h>
+#include <nsIServiceManager.h>
+#include <nsISimpleEnumerator.h>
+#include <nsIX509CertDB.h>
+#include <nsIX509Cert.h>
+#include <nsIX509CertValidity.h>
+#include <nsMemory.h>
+#include <nsServiceManagerUtils.h>
+
+#ifdef HAVE_NSIMUTABLEARRAY_H
+#include <nsIMutableArray.h>
+#endif
+
+#include "ephy-file-helpers.h"
+#include "ephy-gui.h"
+#include "ephy-password-dialog.h"
+#include "ephy-stock-icons.h"
+
+#include "AutoJSContextStack.h"
+#include "AutoWindowModalState.h"
+#include "EphyUtils.h"
+
+#include "GtkNSSDialogs.h"
+
+NS_DEFINE_CID (kX509CertCID, NS_IX509CERT_IID);
+NS_DEFINE_CID (kASN1ObjectCID, NS_IASN1OBJECT_IID);
+
+enum
+{
+ NSSDIALOG_RESPONSE_VIEW_CERT = 10
+};
+
+GtkNSSDialogs::GtkNSSDialogs ()
+{
+}
+
+GtkNSSDialogs::~GtkNSSDialogs ()
+{
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS5 (GtkNSSDialogs,
+ nsICertificateDialogs,
+ nsIBadCertListener,
+ nsITokenPasswordDialogs,
+ nsITokenDialogs,
+ nsIDOMCryptoDialogs)
+
+/* There's also nsICertPickDialogs which is implemented in mozilla
+ * but has no callers. So we don't implement it.
+ * Same for nsIUserCertPicker which is only used in mailnews.
+ */
+
+/**
+ * Call the mozilla service to display a certificate
+ */
+static void
+view_certificate (nsIInterfaceRequestor *ctx, nsIX509Cert *cert)
+{
+ nsresult rv;
+ nsCOMPtr<nsICertificateDialogs> certDialogs =
+ do_GetService (NS_CERTIFICATEDIALOGS_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS (rv, );
+
+ certDialogs->ViewCert (ctx, cert);
+}
+
+/**
+ * Indent a widget according the HIG
+ *
+ * @returns: The new indented widget
+ */
+static GtkWidget*
+higgy_indent_widget (GtkWidget *widget)
+{
+ GtkWidget *hbox;
+ GtkWidget *label;
+
+ hbox = gtk_hbox_new (FALSE, 6);
+
+ label = gtk_label_new (NULL);
+ gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, TRUE, 6);
+ gtk_widget_show (label);
+
+ gtk_box_pack_start (GTK_BOX(hbox), widget, TRUE, TRUE, 0);
+
+ return hbox;
+}
+
+/**
+ * Setup up a dialog with the correct HIG'gy spacings, adding the content_widget
+ */
+static void
+higgy_setup_dialog (GtkDialog *dialog, const gchar *stock_icon,
+ GtkWidget **content_label,
+ GtkWidget **content_vbox)
+{
+ GtkWidget *hbox, *label, *image, *vbox;
+
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+ g_return_if_fail (content_label);
+
+ gtk_dialog_set_has_separator (dialog, FALSE);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
+
+ image = gtk_image_new_from_stock (stock_icon, GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+
+ label = gtk_label_new (NULL);
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+ gtk_widget_show (image);
+ gtk_widget_show (vbox);
+ gtk_widget_show (hbox);
+ gtk_widget_show (label);
+
+ /* Set up the spacing for the dialog internal widgets */
+ gtk_box_set_spacing (GTK_BOX(dialog->vbox), 14); /* 24 = 2 * 5 + 14 */
+
+ *content_label = label;
+ if (content_vbox)
+ {
+ *content_vbox = vbox;
+ }
+}
+
+
+/**
+ * Display a dialog box, showing 'View Certificate', 'Cancel',
+ * and 'Accept' buttons. Optionally a checkbox can be shown,
+ * or the text can be NULL to avoid it being displayed
+ *
+ * @returns: GTK_RESPONSE_ACCEPT if the user clicked Accept
+ */
+static gint
+display_cert_warning_box (nsIInterfaceRequestor *ctx,
+ nsIX509Cert *cert,
+ const char *markup_text,
+ const char *checkbox_text,
+ gboolean *checkbox_value,
+ const char *affirmative_text)
+{
+ GtkWidget *dialog, *label, *checkbox, *vbox, *button;
+ int res;
+
+ g_return_val_if_fail (markup_text, GTK_RESPONSE_CANCEL);
+ g_return_val_if_fail (!checkbox_text || checkbox_value, GTK_RESPONSE_CANCEL);
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ /* NOTE: Due to a mozilla bug [https://bugzilla.mozilla.org/show_bug.cgi?id=306288],
+ * we will always end up without a parent!
+ */
+ nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
+ GtkWindow *gparent = GTK_WINDOW (EphyUtils::FindGtkParent (parent));
+
+ AutoWindowModalState modalState (parent);
+
+ dialog = gtk_dialog_new_with_buttons ("", gparent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ (char *) NULL);
+ if (gparent)
+ {
+ gtk_window_group_add_window (ephy_gui_ensure_window_group (gparent),
+ GTK_WINDOW (dialog));
+ }
+
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ higgy_setup_dialog (GTK_DIALOG (dialog),
+ GTK_STOCK_DIALOG_WARNING, &label, &vbox);
+
+ /* Add the buttons */
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("_View Certificate"),
+ NSSDIALOG_RESPONSE_VIEW_CERT);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+
+ if (affirmative_text == NULL)
+ {
+ affirmative_text = _("_Accept");
+ }
+
+ button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ affirmative_text,
+ GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+
+ if (checkbox_text)
+ {
+ checkbox = gtk_check_button_new_with_mnemonic (checkbox_text);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox),
+ *checkbox_value);
+
+ gtk_box_pack_start (GTK_BOX (vbox), checkbox, TRUE, TRUE, 0);
+ }
+ else
+ {
+ checkbox = 0;
+ }
+
+ /* We don't want focus on the checkbox */
+ gtk_widget_grab_focus (button);
+
+ gtk_label_set_markup (GTK_LABEL (label), markup_text);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+ gtk_widget_show_all (dialog);
+
+ while (1)
+ {
+ res = gtk_dialog_run (GTK_DIALOG (dialog));
+ if (res == NSSDIALOG_RESPONSE_VIEW_CERT)
+ {
+ view_certificate (ctx, cert);
+ continue;
+ }
+
+ break;
+ }
+
+ if (res == GTK_RESPONSE_ACCEPT && checkbox)
+ {
+ *checkbox_value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox));
+ }
+
+ gtk_widget_destroy (dialog);
+ return res;
+}
+
+
+/* Helper functions */
+
+nsresult
+GtkNSSDialogs::GetTokenAndSlotFromName (const PRUnichar *aName,
+ nsIPK11Token **aToken,
+ nsIPKCS11Slot **aSlot)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+ *aToken = nsnull;
+ *aSlot = nsnull;
+
+ nsCOMPtr<nsIPK11TokenDB> tokenDB = do_GetService("@mozilla.org/security/pk11tokendb;1");
+ nsCOMPtr<nsIPKCS11ModuleDB> pkcs11DB = do_GetService("@mozilla.org/security/pkcs11moduledb;1");
+ if (!tokenDB || !pkcs11DB) return rv;
+
+ rv = tokenDB->FindTokenByName (aName, aToken);
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && *aToken, rv);
+
+ pkcs11DB->FindSlotByName (aName, aSlot);
+
+ NS_ENSURE_TRUE (*aSlot, NS_ERROR_FAILURE);
+
+#ifdef GNOME_ENABLE_DEBUG
+ /* Dump some info about this token */
+ nsIPK11Token *token = *aToken;
+ PRUnichar *tName, *tLabel, *tManID, *tHWVersion, *tFWVersion, *tSN;
+ PRInt32 minPwdLen;
+ PRBool needsInit, isHW, needsLogin, isFriendly;
+
+ token->GetTokenName(&tName);
+ token->GetTokenLabel(&tLabel);
+ token->GetTokenManID(&tManID);
+ token->GetTokenHWVersion(&tHWVersion);
+ token->GetTokenFWVersion(&tFWVersion);
+ token->GetTokenSerialNumber(&tSN);
+ token->GetMinimumPasswordLength(&minPwdLen);
+ token->GetNeedsUserInit(&needsInit);
+ token->IsHardwareToken(&isHW);
+ token->NeedsLogin(&needsLogin);
+ token->IsFriendly(&isFriendly);
+
+ g_print ("Token '%s' has \nName: %s\nLabel: %s\nManID: %s\nHWversion: %s\nFWVersion: %s\nSN: %s\n"
+ "MinPwdLen: %d\nNeedsUserInit: %d\nIsHWToken: %d\nNeedsLogin: %d\nIsFriendly: %d\n\n",
+ NS_ConvertUTF16toUTF8(aName).get(),
+
+ NS_ConvertUTF16toUTF8(tName).get(),
+ NS_ConvertUTF16toUTF8(tLabel).get(),
+ NS_ConvertUTF16toUTF8(tManID).get(),
+ NS_ConvertUTF16toUTF8(tHWVersion).get(),
+ NS_ConvertUTF16toUTF8(tFWVersion).get(),
+ NS_ConvertUTF16toUTF8(tSN).get(),
+ minPwdLen,
+ needsInit,
+ isHW,
+ needsLogin,
+ isFriendly);
+
+ nsIPKCS11Slot *slot = *aSlot;
+ PRUnichar*slDesc;
+ slot->GetDesc(&slDesc);
+ g_print ("Slot description: %s\n", NS_ConvertUTF16toUTF8 (slDesc).get());
+#endif
+
+ return NS_OK;
+}
+
+/* nsICertificateDialogs */
+
+NS_IMETHODIMP
+GtkNSSDialogs::ConfirmMismatchDomain (nsIInterfaceRequestor *ctx,
+ const nsACString &targetURL,
+ nsIX509Cert *cert, PRBool *_retval)
+{
+ char *first, *second, *msg;
+ int res;
+
+ nsString commonName;
+ cert->GetCommonName (commonName);
+
+ NS_ConvertUTF16toUTF8 cCommonName (commonName);
+
+ nsCString cTargetUrl (targetURL);
+
+ first = g_markup_printf_escaped (_("The site “%s” returned security information for "
+ "“%s”. It is possible that someone is intercepting "
+ "your communication to obtain your confidential "
+ "information."),
+ cTargetUrl.get(), cCommonName.get());
+
+ second = g_markup_printf_escaped (_("You should only accept the security information if you "
+ "trust “%s” and “%s”."),
+ cTargetUrl.get(), cCommonName.get());
+
+ msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s\n\n%s",
+ _("Accept incorrect security information?"),
+ first, second);
+
+ res = display_cert_warning_box (ctx, cert, msg, NULL, NULL, NULL);
+
+ g_free (second);
+ g_free (first);
+ g_free (msg);
+
+ *_retval = (res == GTK_RESPONSE_ACCEPT);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+GtkNSSDialogs::ConfirmUnknownIssuer (nsIInterfaceRequestor *ctx,
+ nsIX509Cert *cert, PRInt16 *outAddType,
+ PRBool *_retval)
+{
+ gboolean accept_perm = FALSE;
+ char *secondary, *tertiary, *msg;
+ int res;
+
+ nsString commonName;
+ cert->GetCommonName (commonName);
+
+ NS_ConvertUTF16toUTF8 cCommonName (commonName);
+
+ secondary = g_markup_printf_escaped
+ (_("It was not possible to automatically trust “%s”. "
+ "It is possible that someone is intercepting your "
+ "communication to obtain your confidential information."),
+ cCommonName.get());
+
+ tertiary = g_markup_printf_escaped
+ (_("You should only connect to the site if you are certain "
+ "you are connected to “%s”."),
+ cCommonName.get());
+
+ msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s\n\n%s",
+ _("Connect to untrusted site?"),
+ secondary, tertiary);
+
+ res = display_cert_warning_box (ctx, cert, msg,
+ _("_Trust this security information from now on"),
+ &accept_perm, _("Co_nnect"));
+ g_free (tertiary);
+ g_free (secondary);
+ g_free (msg);
+
+ if (res != GTK_RESPONSE_ACCEPT)
+ {
+ *_retval = PR_FALSE;
+ *outAddType = UNINIT_ADD_FLAG;
+ }
+ else
+ {
+ if (accept_perm)
+ {
+ *_retval = PR_TRUE;
+ *outAddType = ADD_TRUSTED_PERMANENTLY;
+ }
+ else
+ {
+ *_retval = PR_TRUE;
+ *outAddType = ADD_TRUSTED_FOR_SESSION;
+ }
+ }
+
+ return NS_OK;
+}
+
+
+/* boolean confirmCertExpired (in nsIInterfaceRequestor socketInfo,
+ in nsIX509Cert cert); */
+NS_IMETHODIMP
+GtkNSSDialogs::ConfirmCertExpired (nsIInterfaceRequestor *ctx,
+ nsIX509Cert *cert, PRBool *_retval)
+{
+ nsresult rv;
+ PRTime now = PR_Now();
+ PRTime notAfter, notBefore, timeToUse;
+ PRInt64 normalizedTime;
+ time_t t;
+ struct tm tm;
+ char formattedDate[128];
+ char *fdate;
+ const char *primary, *text;
+ char *secondary, *msg;
+
+ *_retval = PR_FALSE;
+
+ nsCOMPtr<nsIX509CertValidity> validity;
+ rv = cert->GetValidity (getter_AddRefs(validity));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = validity->GetNotAfter (&notAfter);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = validity->GetNotBefore (&notBefore);
+ if (NS_FAILED(rv)) return rv;
+
+ if (LL_CMP(now, >, notAfter))
+ {
+ primary = _("Accept expired security information?");
+ /* Translators: first %s is a hostname, second %s is a time/date */
+ text = _("The security information for “%s” "
+ "expired on %s.");
+ timeToUse = notAfter;
+ }
+ else
+ {
+ primary = _("Accept not yet valid security information?");
+ /* Translators: first %s is a hostname, second %s is a time/date */
+ text = _("The security information for “%s” isn't valid until %s.");
+ timeToUse = notBefore;
+ }
+
+ nsString commonName;
+ cert->GetCommonName (commonName);
+
+ NS_ConvertUTF16toUTF8 cCommonName (commonName);
+
+ LL_DIV (normalizedTime, timeToUse, PR_USEC_PER_SEC);
+ LL_L2UI (t, normalizedTime);
+ /* To translators: this a time format that is used while displaying the
+ * expiry or start date of an SSL certificate, for the format see
+ * strftime(3) */
+ strftime (formattedDate, sizeof(formattedDate), _("%a %d %b %Y"),
+ localtime_r (&t, &tm));
+ /* FIXME! this isn't actually correct, LC_CTIME codeset could be different than locale codeset! */
+ fdate = g_locale_to_utf8 (formattedDate, -1, NULL, NULL, NULL);
+
+ secondary = g_markup_printf_escaped (text, cCommonName.get(), fdate);
+
+ msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s\n\n%s",
+ primary, secondary,
+ _("You should ensure that your computer's time is correct."));
+
+ int res = display_cert_warning_box (ctx, cert, msg, NULL, NULL, NULL);
+
+ g_free (fdate);
+ g_free (msg);
+ g_free (secondary);
+
+ *_retval = (res == GTK_RESPONSE_ACCEPT);
+
+ return NS_OK;
+}
+
+/* void notifyCrlNextupdate (in nsIInterfaceRequestor socketInfo,
+ in AUTF8String targetURL,
+ in nsIX509Cert cert); */
+NS_IMETHODIMP
+GtkNSSDialogs::NotifyCrlNextupdate (nsIInterfaceRequestor *ctx,
+ const nsACString & targetURL,
+ nsIX509Cert *cert)
+{
+ nsCOMPtr<nsIDOMWindow> parent = do_GetInterface (ctx);
+ GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
+
+ nsCString cTargetUrl (targetURL);
+
+ nsString commonName;
+ cert->GetCommonName (commonName);
+
+ GtkWidget *dialog = gtk_message_dialog_new
+ (GTK_WINDOW (gparent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("Cannot establish connection to “%s”"),
+ cTargetUrl.get ());
+
+ gtk_message_dialog_format_secondary_text
+ (GTK_MESSAGE_DIALOG (dialog),
+ _("The certificate revocation list (CRL) from “%s” "
+ "needs to be updated.\n\n"
+ "Please ask your system administrator for assistance."),
+ NS_ConvertUTF16toUTF8 (commonName).get ());
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ g_signal_connect (dialog, "response",
+ (GCallback) gtk_widget_destroy, NULL);
+
+ gtk_widget_show_all (dialog);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkNSSDialogs::ConfirmDownloadCACert(nsIInterfaceRequestor *ctx,
+ nsIX509Cert *cert,
+ PRUint32 *_trust,
+ PRBool *_retval)
+{
+ GtkWidget *dialog, *label;
+ char *msg, *primary;
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
+ GtkWindow *gparent = GTK_WINDOW (EphyUtils::FindGtkParent (parent));
+
+ AutoWindowModalState modalState (parent);
+
+ dialog = gtk_dialog_new_with_buttons (_("Trust new Certificate Authority?"), gparent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ _("_View Certificate"),
+ NSSDIALOG_RESPONSE_VIEW_CERT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ _("_Trust CA"), GTK_RESPONSE_ACCEPT,
+ (char *) NULL);
+
+ if (gparent)
+ {
+ gtk_window_group_add_window (ephy_gui_ensure_window_group (gparent),
+ GTK_WINDOW (dialog));
+ }
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ higgy_setup_dialog (GTK_DIALOG (dialog), GTK_STOCK_DIALOG_WARNING,
+ &label, NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+
+ nsString commonName;
+ cert->GetCommonName (commonName);
+
+ NS_ConvertUTF16toUTF8 cCommonName (commonName);
+
+ primary = g_markup_printf_escaped (_("Trust new Certificate Authority “%s” to identify web sites?"),
+ cCommonName.get());
+
+ msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
+ primary,
+ _("Before trusting a Certificate Authority (CA) you should "
+ "verify the certificate is authentic."));
+ gtk_label_set_markup (GTK_LABEL (label), msg);
+ g_free (primary);
+ g_free (msg);
+
+ gtk_widget_show_all (dialog);
+ int ret;
+
+ while (1)
+ {
+ ret = gtk_dialog_run (GTK_DIALOG (dialog));
+ if (ret == NSSDIALOG_RESPONSE_VIEW_CERT)
+ {
+ view_certificate (ctx, cert);
+ continue;
+ }
+
+ break;
+ }
+
+ if (ret != GTK_RESPONSE_ACCEPT)
+ {
+ *_retval = PR_FALSE;
+ }
+ else
+ {
+ if (ret == GTK_RESPONSE_ACCEPT)
+ {
+ *_trust |= nsIX509CertDB::TRUSTED_SSL;
+ }
+ else
+ {
+ *_trust = nsIX509CertDB::UNTRUSTED;
+ }
+
+ *_retval = PR_TRUE;
+ }
+ gtk_widget_destroy (dialog);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+GtkNSSDialogs::NotifyCACertExists (nsIInterfaceRequestor *ctx)
+{
+ GtkWidget *dialog, *label;
+ char * msg;
+
+ nsCOMPtr<nsIDOMWindow> parent = do_GetInterface (ctx);
+ GtkWindow *gparent = GTK_WINDOW (EphyUtils::FindGtkParent (parent));
+
+ dialog = gtk_dialog_new_with_buttons ("", gparent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_OK,
+ (char *) NULL);
+
+ if (gparent)
+ {
+ gtk_window_group_add_window (ephy_gui_ensure_window_group (gparent),
+ GTK_WINDOW (dialog));
+ }
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ higgy_setup_dialog (GTK_DIALOG (dialog), GTK_STOCK_DIALOG_ERROR,
+ &label, NULL);
+
+ msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
+ _("Certificate already exists."),
+ _("The certificate has already been imported."));
+ gtk_label_set_markup (GTK_LABEL (label), msg);
+ g_free (msg);
+
+ g_signal_connect (G_OBJECT (dialog),
+ "response",
+ (GCallback)gtk_widget_destroy, NULL);
+
+ gtk_widget_show_all (dialog);
+ return NS_OK;
+}
+
+/* FIXME: This interface sucks! There is way to know the name of the certificate! */
+NS_IMETHODIMP
+GtkNSSDialogs::SetPKCS12FilePassword(nsIInterfaceRequestor *ctx,
+ nsAString &_password,
+ PRBool *_retval)
+{
+ GtkWidget *dialog;
+ char *msg;
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
+ GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
+
+ AutoWindowModalState modalState (parent);
+
+ dialog = ephy_password_dialog_new (gparent,
+ _("Select Password"),
+ EphyPasswordDialogFlags(EPHY_PASSWORD_DIALOG_FLAGS_SHOW_NEW_PASSWORD |
+ EPHY_PASSWORD_DIALOG_FLAGS_SHOW_QUALITY_METER));
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+
+ /* FIXME: set accept button text to (_("_Back Up Certificate") ?
+ * That's not actually correct, since this function is also called from other places!
+ */
+
+ msg = g_markup_printf_escaped (_("Select a password to protect this certificate"));
+ gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), msg);
+ g_free (msg);
+
+ int response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_hide (dialog);
+
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ const char *text = ephy_password_dialog_get_new_password (EPHY_PASSWORD_DIALOG (dialog));
+ g_return_val_if_fail (text != NULL, NS_ERROR_FAILURE);
+ NS_CStringToUTF16 (nsDependentCString (text),
+ NS_CSTRING_ENCODING_UTF8, _password);
+ }
+
+ *_retval = response == GTK_RESPONSE_ACCEPT;
+
+ gtk_widget_destroy (dialog);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkNSSDialogs::GetPKCS12FilePassword(nsIInterfaceRequestor *ctx,
+ nsAString &_password,
+ PRBool *_retval)
+{
+ g_print ("GtkNSSDialogs::GetPKCS12FilePassword\n");
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
+ GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
+
+ AutoWindowModalState modalState (parent);
+
+ GtkWidget *dialog = ephy_password_dialog_new
+ (gparent,
+ "",
+ EphyPasswordDialogFlags (EPHY_PASSWORD_DIALOG_FLAGS_SHOW_PASSWORD));
+ EphyPasswordDialog *password_dialog = EPHY_PASSWORD_DIALOG (dialog);
+ /* FIXME: set accept button text to _("I_mport Certificate") ? */
+
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+
+ /* FIXME: mozilla sucks, no way to get the name of the certificate / cert file! */
+ char *msg = g_markup_printf_escaped (_("Enter the password for this certificate"));
+ gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), msg);
+ g_free (msg);
+
+ int response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ const char *pwd = ephy_password_dialog_get_password (password_dialog);
+ NS_CStringToUTF16 (nsDependentCString (pwd),
+ NS_CSTRING_ENCODING_UTF8, _password);
+ }
+
+ *_retval = response == GTK_RESPONSE_ACCEPT;
+
+ gtk_widget_destroy (dialog);
+
+ return NS_OK;
+}
+
+
+static void
+set_table_row (GtkWidget *table,
+ int& row,
+ const char *title,
+ const char *text)
+{
+ GtkWidget *header, *label;
+ char *bold;
+
+ if (text == NULL || text[0] == 0) return;
+
+ bold = g_markup_printf_escaped ("<b>%s</b>", title);
+ header = gtk_label_new (bold);
+ g_free (bold);
+
+ gtk_label_set_use_markup (GTK_LABEL (header), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (header), 0, 0);
+ gtk_widget_show (header);
+ gtk_table_attach (GTK_TABLE (table), header, 0, 1, row, row+1,
+ GTK_FILL, GTK_FILL, 0, 0);
+
+ label = gtk_label_new (text);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
+ gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+ gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
+ gtk_label_set_max_width_chars (GTK_LABEL (label), 48);
+ gtk_widget_show (label);
+ gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, row, row+1);
+
+ row++;
+}
+
+NS_IMETHODIMP
+GtkNSSDialogs::CrlImportStatusDialog(nsIInterfaceRequestor *ctx, nsICRLInfo *crl)
+{
+
+ GtkWidget *dialog, *label, *table, *vbox;
+ nsresult rv;
+ char *msg;
+
+ nsCOMPtr<nsIDOMWindow> parent = do_GetInterface (ctx);
+ GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
+
+ dialog = gtk_dialog_new_with_buttons ("",
+ GTK_WINDOW (gparent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ (char *) NULL);
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Certificate Revocation List Imported"));
+
+ /* Needed because gparent == NULL always because of mozilla sucks */
+ gtk_window_set_skip_pager_hint (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
+
+ higgy_setup_dialog (GTK_DIALOG (dialog), GTK_STOCK_DIALOG_INFO,
+ &label, &vbox);
+
+ msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>",
+ _("Certificate Revocation List (CRL) successfully imported"));
+ gtk_label_set_markup (GTK_LABEL (label), msg);
+ g_free (msg);
+
+ table = gtk_table_new (2, 3, FALSE);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+
+ nsString org, orgUnit, nextUpdate;
+ rv = crl->GetOrganization (org);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = crl->GetOrganizationalUnit (orgUnit);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = crl->GetNextUpdateLocale (nextUpdate);
+ if (NS_FAILED(rv)) return rv;
+
+ int row = 0;
+ set_table_row (table, row, _("Organization:"), NS_ConvertUTF16toUTF8 (org).get ());
+
+ set_table_row (table, row, _("Unit:"), NS_ConvertUTF16toUTF8 (orgUnit).get ());
+
+ set_table_row (table, row, _("Next Update:"), NS_ConvertUTF16toUTF8 (nextUpdate).get ());
+
+ gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
+
+ gtk_widget_show_all (dialog);
+ g_signal_connect (G_OBJECT (dialog),
+ "response",
+ (GCallback)gtk_widget_destroy, NULL);
+
+ gtk_widget_show_all (dialog);
+ return NS_OK;
+}
+
+/**
+ * Help function to fill in the labels on the General tab
+ */
+static void
+set_label_cert_attribute (GladeXML* gxml, const char* label_id, nsAString &value)
+{
+ GtkWidget *label;
+ label = glade_xml_get_widget (gxml, label_id);
+
+ g_return_if_fail (GTK_IS_LABEL (label));
+
+ if (!value.Length()) {
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ char *msg = g_strdup_printf ("<i>&lt;%s&gt;</i>",
+ _("Not part of certificate"));
+ gtk_label_set_markup (GTK_LABEL (label), msg);
+ g_free (msg);
+ }
+ else
+ {
+ gtk_label_set_use_markup (GTK_LABEL (label), FALSE);
+ gtk_label_set_text (GTK_LABEL (label), NS_ConvertUTF16toUTF8 (value).get());
+ }
+}
+
+
+/**
+ * Do that actual filling in of the certificate tree
+ */
+static gboolean
+fill_cert_chain_tree (GtkTreeView *treeview, nsIArray *certChain)
+{
+ nsresult rv;
+ GtkTreeModel * model = gtk_tree_view_get_model (treeview);
+
+ GtkTreeIter parent;
+ PRUint32 numCerts;
+ rv = certChain->GetLength (&numCerts);
+ if (NS_FAILED(rv) || numCerts < 1) return FALSE;
+
+ for (int i = (int)numCerts-1 ; i >= 0; i--)
+ {
+ nsCOMPtr<nsIX509Cert> nsCert;
+ rv = certChain->QueryElementAt (i, kX509CertCID,
+ getter_AddRefs(nsCert));
+ if (NS_FAILED(rv)) return FALSE;
+
+ GtkTreeIter iter;
+ gtk_tree_store_append (GTK_TREE_STORE (model), &iter,
+ (i == (int)numCerts-1) ? NULL : &parent);
+
+ nsString value;
+ rv = nsCert->GetCommonName (value);
+ if (NS_FAILED(rv)) return FALSE;
+
+ NS_ConvertUTF16toUTF8 cValue (value);
+
+ nsIX509Cert *nsCertP = nsCert;
+ if (value.Length())
+ {
+ gtk_tree_store_set (GTK_TREE_STORE(model), &iter,
+ 0, cValue.get(),
+ 1, nsCertP,
+ -1);
+ }
+ else
+ {
+ char * title;
+ rv = nsCert->GetWindowTitle (&title);
+ if (NS_FAILED(rv)) return FALSE;
+
+ gtk_tree_store_set (GTK_TREE_STORE(model),
+ &iter, 0, title, 1, nsCertP, -1);
+ nsMemory::Free (title);
+ }
+ parent = iter;
+ }
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
+
+ /* And select the last entry, and scroll the view so it's visible */
+ GtkTreeSelection *select = gtk_tree_view_get_selection (treeview);
+ GtkTreePath *path = gtk_tree_model_get_path (model, &parent);
+ gtk_tree_selection_select_path (select, path);
+ gtk_tree_view_scroll_to_cell (treeview, path, NULL, TRUE, 0.5, 0.0);
+ gtk_tree_path_free (path);
+
+ return TRUE;
+}
+
+/**
+ * Add an ASN object to the treeview, recursing if the object was a
+ * sequence
+ */
+static void
+add_asn1_object_to_tree(GtkTreeModel *model, nsIASN1Object *object, GtkTreeIter *parent)
+{
+ nsString dispNameU;
+ object->GetDisplayName(dispNameU);
+
+ GtkTreeIter iter;
+ gtk_tree_store_append (GTK_TREE_STORE (model), &iter, parent);
+
+ gtk_tree_store_set (GTK_TREE_STORE(model), &iter,
+ 0, NS_ConvertUTF16toUTF8 (dispNameU).get(),
+ 1, object,
+ -1);
+
+ nsCOMPtr<nsIASN1Sequence> sequence(do_QueryInterface(object));
+ if (!sequence) return;
+
+ nsCOMPtr<nsIMutableArray> asn1Objects;
+ sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
+
+ PRUint32 numObjects;
+ asn1Objects->GetLength(&numObjects);
+ if (!asn1Objects) return;
+
+ for (PRUint32 i = 0; i < numObjects ; i++)
+ {
+ nsCOMPtr<nsIASN1Object> currObject;
+ asn1Objects->QueryElementAt (i, kASN1ObjectCID,
+ getter_AddRefs (currObject));
+ add_asn1_object_to_tree (model, currObject, &iter);
+ }
+}
+
+
+/**
+ * Update the "Certificate Fields" treeview when a different cert
+ * is selected in the hierarchy text view
+ */
+static void
+cert_chain_tree_view_selection_changed_cb (GtkTreeSelection *selection,
+ GtkWidget* tree_view)
+{
+ GtkTreeIter iter;
+ nsIX509Cert *nsCert;
+ nsresult rv;
+ GtkTreeModel * model;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter, 1, &nsCert, -1);
+
+ nsCOMPtr<nsIASN1Object> object;
+ rv = nsCert->GetASN1Structure (getter_AddRefs(object));
+ if (NS_FAILED(rv)) return;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
+ gtk_tree_store_clear (GTK_TREE_STORE (model));
+ add_asn1_object_to_tree (model, object, NULL);
+
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
+ }
+}
+
+/**
+ * When the "Certificate Field" treeview is changed, update the
+ * text_view to display the value of the currently selected field
+ */
+static void
+field_tree_view_selection_changed_cb (GtkTreeSelection *selection,
+ GtkWidget* text_view)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkTextBuffer * text_buffer =
+ gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ nsIASN1Object *object;
+
+ gtk_tree_model_get (model, &iter, 1, &object, -1);
+
+ nsString dispValU;
+ object->GetDisplayValue(dispValU);
+
+ gtk_text_buffer_set_text (text_buffer, NS_ConvertUTF16toUTF8 (dispValU).get(), -1);
+ }
+ else
+ {
+ gtk_text_buffer_set_text (text_buffer, "", 0);
+ }
+}
+
+/**
+ * Setup the various treeviews, the textview, and fill the treeviews
+ */
+static gboolean
+setup_view_cert_tree (GtkWidget *dialog, GladeXML*gxml, nsIArray *certChain)
+{
+ GtkCellRenderer *renderer;
+ GtkWidget *chain_tree_view, *field_tree_view, *text_view;
+ PangoFontDescription *monospace_font_desc;
+ GConfClient *conf_client;
+ char *monospace_font;
+
+ chain_tree_view = glade_xml_get_widget (gxml, "treeview_cert_chain");
+ field_tree_view = glade_xml_get_widget (gxml, "treeview_cert_info");
+ text_view = glade_xml_get_widget (gxml, "textview_field_value");
+
+ /* Setup the certificate chain view */
+ GtkTreeStore *store = gtk_tree_store_new (2,
+ G_TYPE_STRING,
+ G_TYPE_POINTER);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (chain_tree_view), GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (chain_tree_view),
+ 0, "Certificate",
+ renderer,
+ "text", 0,
+ (char *) NULL);
+
+ GtkTreeSelection *select = gtk_tree_view_get_selection (GTK_TREE_VIEW (chain_tree_view));
+ gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
+
+ g_signal_connect (G_OBJECT (select), "changed",
+ G_CALLBACK (cert_chain_tree_view_selection_changed_cb),
+ field_tree_view);
+
+ /* Setup the certificate field view */
+ store = gtk_tree_store_new (2,
+ G_TYPE_STRING,
+ G_TYPE_POINTER);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (field_tree_view), GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (field_tree_view),
+ 0, "Certificate Field",
+ renderer,
+ "text", 0,
+ (char *) NULL);
+
+ select = gtk_tree_view_get_selection (GTK_TREE_VIEW (field_tree_view));
+ gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
+
+ g_signal_connect (G_OBJECT (select), "changed",
+ G_CALLBACK (field_tree_view_selection_changed_cb),
+ text_view);
+
+ /* Get the text_view displaying a propertional font
+ *
+ * Pick up the monospace font from desktop preferences */
+ conf_client = gconf_client_get_default ();
+ monospace_font = gconf_client_get_string (conf_client,
+ "/desktop/gnome/interface/monospace_font_name", NULL);
+ if (monospace_font)
+ {
+ monospace_font_desc = pango_font_description_from_string (monospace_font);
+ gtk_widget_modify_font (text_view, monospace_font_desc);
+ pango_font_description_free (monospace_font_desc);
+ }
+ g_object_unref (conf_client);
+
+ /* And fill the certificate chain tree */
+ return fill_cert_chain_tree (GTK_TREE_VIEW (chain_tree_view), certChain);
+}
+
+/* void viewCert (in nsIX509Cert cert); */
+NS_IMETHODIMP
+GtkNSSDialogs::ViewCert(nsIInterfaceRequestor *ctx,
+ nsIX509Cert *cert)
+{
+ GtkWidget *dialog, *widget;
+ GladeXML *gxml;
+ nsString value;
+ PRUint32 verifystate, count;
+ PRUnichar ** usage;
+ GtkSizeGroup * sizegroup;
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ gxml = glade_xml_new (ephy_file ("certificate-dialogs.glade"),
+ "viewcert_dialog", NULL);
+ g_return_val_if_fail (gxml != NULL, NS_ERROR_FAILURE);
+
+ dialog = glade_xml_get_widget (gxml, "viewcert_dialog");
+ g_return_val_if_fail (dialog != NULL, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
+ GtkWindow *gparent = GTK_WINDOW (EphyUtils::FindGtkParent (parent));
+
+ AutoWindowModalState modalState (parent);
+
+ if (gparent)
+ {
+ gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(gparent));
+ gtk_window_group_add_window (ephy_gui_ensure_window_group (GTK_WINDOW (gparent)),
+ GTK_WINDOW (dialog));
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+ }
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Certificate Properties"));
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
+
+ /* Set up the GtkSizeGroup so that the columns line up */
+ sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ widget = glade_xml_get_widget (gxml, "label_size1");
+ gtk_size_group_add_widget (sizegroup, widget);
+ widget = glade_xml_get_widget (gxml, "label_size2");
+ gtk_size_group_add_widget (sizegroup, widget);
+ widget = glade_xml_get_widget (gxml, "label_size3");
+ gtk_size_group_add_widget (sizegroup, widget);
+ widget = glade_xml_get_widget (gxml, "label_size4");
+ gtk_size_group_add_widget (sizegroup, widget);
+ g_object_unref (sizegroup);
+
+ rv = cert->GetUsagesArray (FALSE, &verifystate, &count, &usage);
+ if (NS_FAILED(rv)) return rv;
+
+ const char * text;
+ switch (verifystate)
+ {
+ case nsIX509Cert::VERIFIED_OK:
+ text = _("This certificate has been verified for the following uses:");
+ break;
+ case nsIX509Cert::CERT_REVOKED:
+ text = _("Could not verify this certificate because it has been revoked.");
+ break;
+ case nsIX509Cert::CERT_EXPIRED:
+ text = _("Could not verify this certificate because it has expired.");
+ break;
+ case nsIX509Cert::CERT_NOT_TRUSTED:
+ text = _("Could not verify this certificate because it is not trusted.");
+ break;
+ case nsIX509Cert::ISSUER_NOT_TRUSTED:
+ text = _("Could not verify this certificate because the issuer is not trusted.");
+ break;
+ case nsIX509Cert::ISSUER_UNKNOWN:
+ text = _("Could not verify this certificate because the issuer is unknown.");
+ break;
+ case nsIX509Cert::INVALID_CA:
+ text = _("Could not verify this certificate because the CA certificate is invalid.");
+ break;
+ case nsIX509Cert::NOT_VERIFIED_UNKNOWN:
+ case nsIX509Cert::USAGE_NOT_ALLOWED:
+ default:
+ text = _("Could not verify this certificate for unknown reasons.");
+ }
+
+ char *vmsg = g_strdup_printf ("<b>%s</b>", text);
+ widget = glade_xml_get_widget (gxml, "label_verify_text");
+ g_return_val_if_fail (GTK_IS_LABEL (widget), NS_ERROR_FAILURE);
+ gtk_label_set_markup (GTK_LABEL (widget), vmsg);
+ g_free (vmsg);
+
+ if (count > 0)
+ {
+ GtkWidget *vbox = gtk_vbox_new (FALSE, 3);
+ GtkWidget *indent;
+ for (PRUint32 i = 0 ; i < count ; i++)
+ {
+ GtkWidget *label = gtk_label_new (NS_ConvertUTF16toUTF8 (usage[i]).get());
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+ nsMemory::Free (usage[i]);
+ }
+ nsMemory::Free (usage);
+ indent = higgy_indent_widget (vbox);
+ widget = glade_xml_get_widget (gxml, "vbox_validity");
+ g_return_val_if_fail (GTK_IS_BOX (widget), NS_ERROR_FAILURE);
+
+ gtk_box_pack_start (GTK_BOX (widget), indent, FALSE, FALSE, 0);
+ }
+
+ cert->GetCommonName (value);
+ set_label_cert_attribute (gxml, "label_cn", value);
+
+ cert->GetOrganization (value);
+ set_label_cert_attribute (gxml, "label_o", value);
+
+ cert->GetOrganizationalUnit (value);
+ set_label_cert_attribute (gxml, "label_ou", value);
+
+ cert->GetSerialNumber (value);
+ set_label_cert_attribute (gxml, "label_serial", value);
+
+ rv = cert->GetIssuerCommonName (value);
+ if (NS_FAILED(rv)) return rv;
+ set_label_cert_attribute (gxml, "label_issuer_cn", value);
+
+ cert->GetIssuerOrganization (value);
+ set_label_cert_attribute (gxml, "label_issuer_o", value);
+
+ cert->GetIssuerOrganizationUnit (value);
+ set_label_cert_attribute (gxml, "label_issuer_ou", value);
+
+ nsCOMPtr<nsIX509CertValidity> validity;
+ rv = cert->GetValidity (getter_AddRefs(validity));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = validity->GetNotAfterLocalDay (value);
+ if (NS_FAILED(rv)) return rv;
+ set_label_cert_attribute (gxml, "label_notafter", value);
+
+ rv = validity->GetNotBeforeLocalDay (value);
+ if (NS_FAILED(rv)) return rv;
+ set_label_cert_attribute (gxml, "label_notbefore", value);
+
+ cert->GetSha1Fingerprint (value);
+ set_label_cert_attribute (gxml, "label_sha_print", value);
+
+ cert->GetMd5Fingerprint (value);
+ set_label_cert_attribute (gxml, "label_md5_print", value);
+
+ /* Hold a reference to each certificate in the chain while the
+ * dialog is displayed, this holds the reference for the ASN
+ * objects as well */
+
+ nsCOMPtr<nsIArray> certChain;
+ rv = cert->GetChain (getter_AddRefs(certChain));
+ if (NS_FAILED(rv)) return rv;
+
+ gboolean ret = setup_view_cert_tree (dialog, gxml, certChain);
+ if (ret == FALSE) return NS_ERROR_FAILURE;
+
+ g_object_unref (gxml);
+
+ gtk_widget_show_all (dialog);
+
+ int res;
+ while (1)
+ {
+ res = gtk_dialog_run (GTK_DIALOG (dialog));
+ if (res == GTK_RESPONSE_HELP)
+ {
+ ephy_gui_help (GTK_WINDOW (dialog), "epiphany", "using-certificate-viewer");
+ continue;
+ }
+ break;
+ }
+
+ gtk_widget_destroy (dialog);
+ return NS_OK;
+}
+
+/* nsITokenPasswordDialogs */
+
+/* NOTE: This interface totally sucks, see https://bugzilla.mozilla.org/show_bug.cgi?id=306993 */
+
+/* void setPassword (in nsIInterfaceRequestor ctx, in wstring tokenName, out boolean canceled); */
+NS_IMETHODIMP
+GtkNSSDialogs::SetPassword(nsIInterfaceRequestor *aCtx,
+ const PRUnichar *aTokenName,
+ PRBool *aCancelled)
+{
+ NS_ENSURE_ARG_POINTER(aCancelled);
+
+ nsresult rv;
+ nsCOMPtr<nsIPK11Token> token;
+ nsCOMPtr<nsIPKCS11Slot> slot;
+ rv = GetTokenAndSlotFromName (aTokenName, getter_AddRefs (token),
+ getter_AddRefs (slot));
+ NS_ENSURE_SUCCESS (rv, rv);
+ NS_ENSURE_TRUE (token && slot, NS_ERROR_FAILURE);
+
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ PRUint32 status = nsIPKCS11Slot::SLOT_UNINITIALIZED;
+ slot->GetStatus (&status);
+
+ nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (aCtx));
+ GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
+
+ AutoWindowModalState modalState (parent);
+
+ EphyPasswordDialogFlags flags =
+ EphyPasswordDialogFlags (EPHY_PASSWORD_DIALOG_FLAGS_SHOW_NEW_PASSWORD |
+ EPHY_PASSWORD_DIALOG_FLAGS_SHOW_QUALITY_METER);
+ if (status != nsIPKCS11Slot::SLOT_UNINITIALIZED)
+ flags = EphyPasswordDialogFlags (flags | EPHY_PASSWORD_DIALOG_FLAGS_SHOW_PASSWORD);
+
+ GtkWidget *dialog = ephy_password_dialog_new
+ (gparent,
+ _("Change Token Password"),
+ flags);
+ EphyPasswordDialog *password_dialog = EPHY_PASSWORD_DIALOG (dialog);
+
+ char *message;
+ if (status == nsIPKCS11Slot::SLOT_UNINITIALIZED) {
+ message = g_markup_printf_escaped (_("Choose a password for the “%s” token"),
+ NS_ConvertUTF16toUTF8 (aTokenName).get ());
+ } else {
+ message = g_markup_printf_escaped (_("Change the password for the “%s” token"),
+ NS_ConvertUTF16toUTF8 (aTokenName).get ());
+ }
+
+ gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog),
+ message);
+ g_free (message);
+
+ int response;
+ nsString oldPassword;
+ PRBool pwdOk, needsLogin;
+ do {
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ if (status != nsIPKCS11Slot::SLOT_UNINITIALIZED)
+ {
+ const char *pwd = ephy_password_dialog_get_password (password_dialog);
+ oldPassword = NS_ConvertUTF8toUTF16 (pwd);
+ }
+ } while (response == GTK_RESPONSE_OK &&
+ status != nsIPKCS11Slot::SLOT_UNINITIALIZED &&
+ NS_SUCCEEDED (token->NeedsLogin (&needsLogin)) && needsLogin &&
+ NS_SUCCEEDED (token->CheckPassword (oldPassword.get (), &pwdOk) &&
+ !pwdOk));
+
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ const char *pwd = ephy_password_dialog_get_new_password (password_dialog);
+
+ NS_ConvertUTF8toUTF16 newPassword (pwd);
+
+ if (status == nsIPKCS11Slot::SLOT_UNINITIALIZED)
+ {
+ rv = token->InitPassword (newPassword.get ());
+ }
+ else
+ {
+ rv = token->ChangePassword (oldPassword.get (),
+ newPassword.get ());
+ }
+ }
+ else
+ {
+ rv = NS_OK;
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ *aCancelled = response != GTK_RESPONSE_ACCEPT;
+
+ return rv;
+}
+
+/* void getPassword (in nsIInterfaceRequestor ctx, in wstring tokenName, out wstring password, out boolean canceled); */
+NS_IMETHODIMP
+GtkNSSDialogs::GetPassword(nsIInterfaceRequestor *aCtx,
+ const PRUnichar *aTokenName,
+ PRUnichar **aPassword,
+ PRBool *aCancelled)
+{
+ NS_ENSURE_ARG_POINTER(aCancelled);
+
+ nsresult rv;
+ nsCOMPtr<nsIPK11Token> token;
+ nsCOMPtr<nsIPKCS11Slot> slot;
+ rv = GetTokenAndSlotFromName (aTokenName, getter_AddRefs (token),
+ getter_AddRefs (slot));
+ NS_ENSURE_SUCCESS (rv, rv);
+ NS_ENSURE_TRUE (token && slot, NS_ERROR_FAILURE);
+
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (aCtx));
+ GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
+
+ AutoWindowModalState modalState (parent);
+
+ EphyPasswordDialogFlags flags =
+ EphyPasswordDialogFlags (EPHY_PASSWORD_DIALOG_FLAGS_SHOW_PASSWORD);
+
+ GtkWidget *dialog = ephy_password_dialog_new
+ (gparent,
+ _("Get Token Password"), /* FIXME */
+ flags);
+ EphyPasswordDialog *password_dialog = EPHY_PASSWORD_DIALOG (dialog);
+
+ /* Translators: A "token" is something that enables the user to authenticate himself or
+ * prove his credentials. This can be either a hardware device (e.g. a smart-card), or
+ * a data file (e.g. a cryptographic certificate).
+ */
+ char *message = g_markup_printf_escaped (_("Please enter the password for the “%s” token"),
+ NS_ConvertUTF16toUTF8 (aTokenName).get ());
+ gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog),
+ message);
+ g_free (message);
+
+ int response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ const char *pwd = ephy_password_dialog_get_password (password_dialog);
+ *aPassword = NS_StringCloneData (NS_ConvertUTF8toUTF16 (pwd));
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ *aCancelled = response != GTK_RESPONSE_ACCEPT;
+
+ return NS_OK;
+}
+
+/* nsITokenDialogs */
+
+static void
+SelectionChangedCallback (GtkComboBox *combo,
+ GtkDialog *dialog)
+{
+ int active = gtk_combo_box_get_active (combo);
+ gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_ACCEPT, active >= 0);
+}
+
+/* void ChooseToken (in nsIInterfaceRequestor ctx,
+ [array, size_is (count)] in wstring tokenNameList,
+ in unsigned long count,
+ out wstring tokenName,
+ out boolean canceled); */
+NS_IMETHODIMP
+GtkNSSDialogs::ChooseToken (nsIInterfaceRequestor *aContext,
+ const PRUnichar **tokenNameList,
+ PRUint32 count,
+ PRUnichar **_tokenName,
+ PRBool *_cancelled)
+{
+ NS_ENSURE_ARG (tokenNameList);
+ NS_ENSURE_ARG (count);
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ /* Didn't you know it? MOZILLA SUCKS! ChooseToken is always called with |aContext| == NULL! See
+ * http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/manager/ssl/src/nsKeygenHandler.cpp&rev=1.39&mark=346#346
+ * Need to investigate if we it's always called directly from code called from JS, in which case we
+ * can use EphyJSUtils::GetDOMWindowFromCallContext.
+ */
+ nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (aContext));
+ GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
+
+ AutoWindowModalState modalState (parent);
+
+ GtkWidget *dialog = gtk_message_dialog_new
+ (GTK_WINDOW (gparent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_OTHER,
+ GTK_BUTTONS_CANCEL,
+ _("Please select a token:"));
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ GtkWidget *combo = gtk_combo_box_new_text ();
+ for (PRUint32 i = 0; i < count; ++i) {
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combo),
+ NS_ConvertUTF16toUTF8 (tokenNameList[i]).get ());
+ }
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), -1);
+ g_signal_connect (combo, "changed",
+ G_CALLBACK (SelectionChangedCallback), dialog);
+
+ /* FIXME: View Cert button? */
+
+ GtkWidget *vbox = GTK_MESSAGE_DIALOG (dialog)->label->parent;
+ gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("_Select"),
+ GTK_RESPONSE_ACCEPT);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
+
+ int response = gtk_dialog_run (GTK_DIALOG (dialog));
+ int selected = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+
+ gtk_widget_destroy (dialog);
+
+ *_cancelled = response != GTK_RESPONSE_ACCEPT;
+
+ if (response == GTK_RESPONSE_ACCEPT) {
+ NS_ENSURE_TRUE (selected >= 0 && selected < (int) count, NS_ERROR_FAILURE);
+ *_tokenName = NS_StringCloneData (nsDependentString (tokenNameList[selected]));
+ }
+
+ return NS_OK;
+}
+
+/* nsIDOMCryptoDialogs */
+
+/* Note: this interface sucks! See https://bugzilla.mozilla.org/show_bug.cgi?id=341914 */
+
+/* boolean ConfirmKeyEscrow (in nsIX509Cert escrowAuthority); */
+NS_IMETHODIMP
+GtkNSSDialogs::ConfirmKeyEscrow (nsIX509Cert *aEscrowAuthority,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG (aEscrowAuthority);
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+#if 0
+ nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (aCtx));
+#endif
+ nsCOMPtr<nsIDOMWindow> parent (EphyJSUtils::GetDOMWindowFromCallContext ());
+ GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
+
+ AutoWindowModalState modalState (parent);
+
+ /* FIXME: is that guaranteed to be non-empty? */
+ nsString commonName;
+ aEscrowAuthority->GetCommonName (commonName);
+
+ GtkWidget *dialog = gtk_message_dialog_new
+ (GTK_WINDOW (gparent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING /* QUESTION really but it's also a strong warnings... */,
+ GTK_BUTTONS_NONE,
+ _("Escrow the secret key?"));
+
+ /* FIXME: If I understand the documentation of generateCRMFRequest
+ * correctly, key escrow is never used for signing keys (if it were,
+ * we'd have to warn that the cert authority can forge your signature
+ * too).
+ */
+ gtk_message_dialog_format_secondary_text
+ (GTK_MESSAGE_DIALOG (dialog),
+ _("The certificate authority “%s” requests that you give it a copy "
+ "of the newly generated secret key.\n\n"
+ "This will enable the certificate authority read any "
+ "communications encrypted with this key "
+ "without your knowledge or consent.\n\n"
+ "It is strongly recommended not to allow it."),
+ NS_ConvertUTF16toUTF8 (commonName).get ());
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ GtkWidget *button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("_Reject"),
+ GTK_RESPONSE_REJECT);
+ gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("_Allow"),
+ GTK_RESPONSE_ACCEPT);
+ /* FIXME: View Cert button? */
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
+ gtk_widget_grab_focus (button);
+
+ int response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ *_retval = response == GTK_RESPONSE_ACCEPT;
+
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/GtkNSSDialogs.h b/embed/xulrunner/embed/GtkNSSDialogs.h
new file mode 100644
index 000000000..2edd1ffbe
--- /dev/null
+++ b/embed/xulrunner/embed/GtkNSSDialogs.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2003 Crispin Flowerday <gnome@flowerday.cx>
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef GTKNSSDIALOGS_H
+#define GTKNSSDIALOGS_H 1
+
+#include <nsIBadCertListener.h>
+#include <nsICertificateDialogs.h>
+#include <nsITokenPasswordDialogs.h>
+#include <nsITokenDialogs.h>
+#include <nsIDOMCryptoDialogs.h>
+
+class nsIPK11Token;
+class nsIPKCS11Slot;
+
+/* 7a50a10d-9425-4e12-84b1-5822edacd8ce */
+#define GTK_NSSDIALOGS_CID \
+ {0x7a50a10d, 0x9425, 0x4e12, {0x84, 0xb1, 0x58, 0x22, 0xed, 0xac, 0xd8, 0xce}}
+
+#define GTK_NSSDIALOGS_CLASSNAME "Gtk NSS Dialogs"
+
+class GtkNSSDialogs : public nsIBadCertListener,
+ public nsICertificateDialogs,
+ public nsITokenPasswordDialogs,
+ public nsITokenDialogs,
+ public nsIDOMCryptoDialogs
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIBADCERTLISTENER
+ NS_DECL_NSICERTIFICATEDIALOGS
+ NS_DECL_NSITOKENPASSWORDDIALOGS
+ NS_DECL_NSITOKENDIALOGS
+ NS_DECL_NSIDOMCRYPTODIALOGS
+
+ GtkNSSDialogs();
+ virtual ~GtkNSSDialogs();
+
+ private:
+ nsresult GetTokenAndSlotFromName(const PRUnichar*, nsIPK11Token**, nsIPKCS11Slot**);
+};
+
+#endif /* GTKNSSDIALOGS_H */
diff --git a/embed/xulrunner/embed/GtkNSSKeyPairDialogs.cpp b/embed/xulrunner/embed/GtkNSSKeyPairDialogs.cpp
new file mode 100644
index 000000000..3b9e405cc
--- /dev/null
+++ b/embed/xulrunner/embed/GtkNSSKeyPairDialogs.cpp
@@ -0,0 +1,216 @@
+/*
+ * GtkNSSKeyPairDialogs.cpp
+ *
+ * Copyright © 2003 Crispin Flowerday <gnome@flowerday.cx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+/*
+ * This file provides Gtk implementations of the mozilla Generating Key Pair
+ * dialogs.
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtkprogressbar.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkvbox.h>
+
+#include <nsIDOMWindow.h>
+#include <nsIInterfaceRequestor.h>
+#include <nsIInterfaceRequestorUtils.h>
+#include <nsIKeygenThread.h>
+#include <nsIObserver.h>
+#include <nsIServiceManager.h>
+
+#include "ephy-debug.h"
+#include "ephy-gui.h"
+#include "ephy-stock-icons.h"
+
+#include "AutoJSContextStack.h"
+#include "AutoWindowModalState.h"
+#include "EphyUtils.h"
+
+#include "GtkNSSKeyPairDialogs.h"
+
+GtkNSSKeyPairDialogs::GtkNSSKeyPairDialogs ()
+{
+ LOG ("GtkNSSKeyPairDialogs ctor (%p)", this);
+}
+
+GtkNSSKeyPairDialogs::~GtkNSSKeyPairDialogs ()
+{
+ LOG ("GtkNSSKeyPairDialogs dtor (%p)", this);
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1 (GtkNSSKeyPairDialogs,
+ nsIGeneratingKeypairInfoDialogs)
+
+class KeyPairObserver : public nsIObserver
+{
+public:
+ NS_DECL_NSIOBSERVER
+ NS_DECL_ISUPPORTS
+
+ KeyPairObserver() : close_called (FALSE) {};
+ virtual ~KeyPairObserver() {};
+
+ gboolean close_called;
+};
+
+NS_IMPL_ISUPPORTS1 (KeyPairObserver, nsIObserver);
+
+NS_IMETHODIMP KeyPairObserver::Observe (nsISupports *aSubject, const char *aTopic,
+ const PRUnichar *aData)
+{
+ close_called = TRUE;
+ return NS_OK;
+}
+
+/* ------------------------------------------------------------ */
+static void
+begin_busy (GtkWidget *widget)
+{
+ static GdkCursor *cursor = NULL;
+
+ if (cursor == NULL) cursor = gdk_cursor_new (GDK_WATCH);
+
+ if (!GTK_WIDGET_REALIZED (widget)) gtk_widget_realize (GTK_WIDGET(widget));
+
+ gdk_window_set_cursor (GTK_WIDGET (widget)->window, cursor);
+
+ /* Eek! FIXME: AutoJSContextStack! */
+ while (gtk_events_pending ()) gtk_main_iteration ();
+}
+
+static void
+end_busy (GtkWidget *widget)
+{
+ gdk_window_set_cursor (GTK_WIDGET(widget)->window, NULL);
+}
+
+
+struct KeyPairInfo
+{
+ GtkWidget *progress;
+ GtkWidget *dialog;
+ KeyPairObserver *helper;
+};
+
+
+static gboolean
+generating_timeout_cb (KeyPairInfo *info)
+{
+ gtk_progress_bar_pulse (GTK_PROGRESS_BAR (info->progress));
+
+ if (info->helper->close_called)
+ {
+ gtk_dialog_response (GTK_DIALOG (info->dialog), GTK_RESPONSE_OK);
+ }
+ return TRUE;
+}
+
+
+/* void displayGeneratingKeypairInfo (in nsIInterfaceRequestor ctx,
+ in nsIKeygenThread runnable); */
+NS_IMETHODIMP
+GtkNSSKeyPairDialogs::DisplayGeneratingKeypairInfo (nsIInterfaceRequestor *ctx,
+ nsIKeygenThread *runnable)
+{
+ GtkWidget *dialog, *progress, *label, *vbox;
+ gint timeout_id;
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ nsCOMPtr<nsIDOMWindow> parent = do_GetInterface (ctx);
+ GtkWindow *gparent = GTK_WINDOW (EphyUtils::FindGtkParent (parent));
+
+ AutoWindowModalState modalState (parent);
+
+ dialog = gtk_dialog_new_with_buttons ("", gparent,
+ GTK_DIALOG_DESTROY_WITH_PARENT, (char *) NULL);
+
+ if (gparent)
+ {
+ gtk_window_group_add_window (ephy_gui_ensure_window_group (gparent),
+ GTK_WINDOW (dialog));
+ }
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+ gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox, TRUE, TRUE, 0);
+
+ label = gtk_label_new (NULL);
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+ gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
+
+ char *msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
+ _("Generating Private Key."),
+ _("Please wait while a new private key is "
+ "generated. This process could take a few minutes." ));
+ gtk_label_set_markup (GTK_LABEL(label), msg);
+ g_free (msg);
+
+ progress = gtk_progress_bar_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), progress, TRUE, TRUE, 0);
+
+ /* Create a helper class that just waits for close events
+ * from the other thread */
+ nsCOMPtr<KeyPairObserver> helper = new KeyPairObserver;
+
+ KeyPairInfo callback_data = { progress, dialog, helper };
+ timeout_id = g_timeout_add (100, (GSourceFunc)generating_timeout_cb, &callback_data);
+
+ gtk_widget_show_all (dialog);
+ gtk_widget_hide (GTK_DIALOG (dialog)->action_area);
+
+ begin_busy (dialog);
+ runnable->StartKeyGeneration (helper);
+ int res = gtk_dialog_run (GTK_DIALOG (dialog));
+ if (res != GTK_RESPONSE_OK && helper->close_called == FALSE)
+ {
+ /* Ignore the already_closed flag, our nsIDOMWindowInterna::Close
+ * function just sets a flag, it doesn't close the window, so we
+ * dont have a race condition */
+ PRBool already_closed = FALSE;
+ runnable->UserCanceled (&already_closed);
+ }
+
+ g_source_remove (timeout_id);
+ end_busy (dialog);
+ gtk_widget_destroy (dialog);
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/GtkNSSKeyPairDialogs.h b/embed/xulrunner/embed/GtkNSSKeyPairDialogs.h
new file mode 100644
index 000000000..f4b92d9e1
--- /dev/null
+++ b/embed/xulrunner/embed/GtkNSSKeyPairDialogs.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2003 Crispin Flowerday <gnome@flowerday.cx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * $Id$
+ */
+
+#ifndef GTKNSSKEYPAIRDIALOGS_H
+#define GTKNSSKEYPAIRDIALOGS_H 1
+
+#include <nsIGenKeypairInfoDlg.h>
+
+// 6a8b1aff-ae8b-4751-982e-4ce5ad544100
+#define GTK_NSSKEYPAIRDIALOGS_CID \
+ {0x6a8b1aff, 0xae8b, 0x4751, {0x98, 0x2e, 0x4c, 0xe5, 0xad, 0x54, 0x41, 0x10}}
+
+#define GTK_NSSKEYPAIRDIALOGS_CLASSNAME "Gtk NSS Key Pair Dialogs"
+
+class GtkNSSKeyPairDialogs
+: public nsIGeneratingKeypairInfoDialogs
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIGENERATINGKEYPAIRINFODIALOGS
+
+ GtkNSSKeyPairDialogs();
+ virtual ~GtkNSSKeyPairDialogs();
+};
+
+
+#endif /* GTKNSSKEYPAIRDIALOGS_H */
diff --git a/embed/xulrunner/embed/GtkNSSSecurityWarningDialogs.cpp b/embed/xulrunner/embed/GtkNSSSecurityWarningDialogs.cpp
new file mode 100644
index 000000000..b50b3762a
--- /dev/null
+++ b/embed/xulrunner/embed/GtkNSSSecurityWarningDialogs.cpp
@@ -0,0 +1,285 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Terry Hayes <thayes@netscape.com>
+ * Javier Delgadillo <javi@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * Copyright © 2005 Christian Persch
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtkbox.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkvbox.h>
+
+#include "ephy-stock-icons.h"
+
+#include <nsCOMPtr.h>
+#include <nsIDOMWindow.h>
+#include <nsIInterfaceRequestor.h>
+#include <nsIInterfaceRequestorUtils.h>
+#include <nsIPrefBranch.h>
+#include <nsIPrefService.h>
+#include <nsIServiceManager.h>
+#include <nsServiceManagerUtils.h>
+
+#include "AutoJSContextStack.h"
+#include "AutoWindowModalState.h"
+#include "EphyUtils.h"
+
+#include "GtkNSSSecurityWarningDialogs.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1 (GtkNSSSecurityWarningDialogs, nsISecurityWarningDialogs)
+
+#define ENTER_SITE_PREF "security.warn_entering_secure"
+#define WEAK_SITE_PREF "security.warn_entering_weak"
+#define MIXEDCONTENT_PREF "security.warn_viewing_mixed"
+#define INSECURE_SUBMIT_PREF "security.warn_submit_insecure"
+
+GtkNSSSecurityWarningDialogs::GtkNSSSecurityWarningDialogs()
+{
+}
+
+GtkNSSSecurityWarningDialogs::~GtkNSSSecurityWarningDialogs()
+{
+}
+
+NS_IMETHODIMP
+GtkNSSSecurityWarningDialogs::ConfirmEnteringSecure (nsIInterfaceRequestor *aContext,
+ PRBool *_retval)
+{
+ DoDialog (aContext,
+ ENTER_SITE_PREF,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ GTK_RESPONSE_OK,
+ _("Security Notice"),
+ _("This page is loaded over a secure connection"),
+ _("For secure pages, the address entry has a distinct "
+ "color and a locked padlock icon is displayed.\n\n"
+ "The padlock icon in the statusbar also indicates "
+ "whether a page is secure."),
+ nsnull, _retval);
+
+ *_retval = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkNSSSecurityWarningDialogs::ConfirmEnteringWeak (nsIInterfaceRequestor *aContext,
+ PRBool *_retval)
+{
+ DoDialog (aContext,
+ WEAK_SITE_PREF,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK,
+ GTK_RESPONSE_OK,
+ _("Security Warning"),
+ _("This page is loaded over a low security connection"),
+ _("Any information you see or enter on this page could "
+ "easily be intercepted by a third party."),
+ nsnull, _retval);
+
+ *_retval = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkNSSSecurityWarningDialogs::ConfirmLeavingSecure (nsIInterfaceRequestor *aContext,
+ PRBool *_retval)
+{
+ /* don't prompt */
+ *_retval = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkNSSSecurityWarningDialogs::ConfirmMixedMode (nsIInterfaceRequestor *aContext,
+ PRBool *_retval)
+{
+ DoDialog (aContext,
+ MIXEDCONTENT_PREF,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK,
+ GTK_RESPONSE_OK,
+ _("Security Warning"),
+ _("Some parts of this page are loaded over an insecure connection"),
+ _("Some information you see or enter will be sent over an insecure "
+ "connection, and could easily be intercepted by a third party."),
+ nsnull, _retval);
+
+ *_retval = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkNSSSecurityWarningDialogs::ConfirmPostToInsecure (nsIInterfaceRequestor *aContext,
+ PRBool* _retval)
+{
+ DoDialog (aContext,
+ INSECURE_SUBMIT_PREF,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_CANCEL,
+ GTK_RESPONSE_ACCEPT,
+ _("Security Warning"),
+ _("Send this information over an insecure connection?"),
+ _("The information you have entered will be sent over an "
+ "insecure connection, and could easily be intercepted "
+ "by a third party."),
+ _("_Send"),
+ _retval);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkNSSSecurityWarningDialogs::ConfirmPostToInsecureFromSecure (nsIInterfaceRequestor *aContext,
+ PRBool* _retval)
+{
+ DoDialog (aContext,
+ nsnull, /* No preference for this one - it's too important */
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ _("Security Warning"),
+ _("Send this information over an insecure connection?"),
+ _("Although this page was loaded over a secure connection, "
+ "the information you have entered will be sent over an "
+ "insecure connection, and could easily be intercepted by "
+ "a third party."),
+ _("_Send"),
+ _retval);
+
+ return NS_OK;
+}
+
+void
+GtkNSSSecurityWarningDialogs::DoDialog (nsIInterfaceRequestor *aContext,
+ const char *aPrefName,
+ GtkMessageType aType,
+ GtkButtonsType aButtons,
+ int aDefaultResponse,
+ const char *aTitle,
+ const char *aPrimary,
+ const char *aSecondary,
+ const char *aButtonText,
+ PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+
+ nsresult rv;
+ PRBool show = PR_TRUE;
+ nsCOMPtr<nsIPrefBranch> prefBranch
+ (do_GetService (NS_PREFSERVICE_CONTRACTID));
+ if (prefBranch && aPrefName)
+ {
+ rv = prefBranch->GetBoolPref (aPrefName, &show);
+ if (NS_FAILED(rv)) show = PR_TRUE;
+ }
+
+ char *showOncePref = NULL;
+ PRBool showOnce = PR_FALSE;
+ if (!show && prefBranch && aPrefName)
+ {
+ showOncePref = g_strconcat (aPrefName, ".show_once", (char *) NULL);
+ rv = prefBranch->GetBoolPref (showOncePref, &showOnce);
+ if (NS_FAILED (rv)) showOnce = PR_FALSE;
+ }
+
+ if (!show && !showOnce)
+ {
+ g_free (showOncePref);
+ *_retval = PR_TRUE;
+ return;
+ }
+
+ /* On 1.8.0, domWin will be always nsnull, because of
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=277587
+ */
+ nsCOMPtr<nsIDOMWindow> domWin (do_GetInterface (aContext));
+ GtkWidget *parent = EphyUtils::FindGtkParent (domWin);
+
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return;
+
+ AutoWindowModalState modalState (domWin);
+
+ GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
+ GTK_DIALOG_MODAL, aType,
+ aButtons, aPrimary);
+
+ if (parent && GTK_WINDOW (parent)->group)
+ {
+ gtk_window_group_add_window (GTK_WINDOW (parent)->group,
+ GTK_WINDOW (dialog));
+ }
+
+ if (aSecondary)
+ {
+ gtk_message_dialog_format_secondary_text
+ (GTK_MESSAGE_DIALOG (dialog), aSecondary);
+ }
+
+ if (aButtonText)
+ {
+ gtk_dialog_add_button (GTK_DIALOG (dialog), aButtonText,
+ GTK_RESPONSE_ACCEPT);
+ }
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), aDefaultResponse);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), aTitle);
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
+
+ int response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ *_retval = (response == GTK_RESPONSE_ACCEPT || response == GTK_RESPONSE_OK);
+
+ if (prefBranch && showOncePref && showOnce && *_retval)
+ {
+ prefBranch->SetBoolPref (showOncePref, PR_FALSE);
+ }
+
+ g_free (showOncePref);
+}
diff --git a/embed/xulrunner/embed/GtkNSSSecurityWarningDialogs.h b/embed/xulrunner/embed/GtkNSSSecurityWarningDialogs.h
new file mode 100644
index 000000000..a84ea6585
--- /dev/null
+++ b/embed/xulrunner/embed/GtkNSSSecurityWarningDialogs.h
@@ -0,0 +1,83 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Terry Hayes <thayes@netscape.com>
+ * Javier Delgadillo <javi@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * Copyright © 2005 Christian Persch
+ *
+ * $Id$
+ */
+
+#ifndef GTK_NSSSECURITYDIALOGS_H
+#define GTK_NSSSECURITYDIALOGS_H
+
+#include <gtk/gtkmessagedialog.h>
+
+#include <nsISecurityWarningDialogs.h>
+
+#define GTK_NSSSECURITYWARNINGDIALOGS_CLASSNAME "Epiphany Security Warning Dialogs Class"
+#define GTK_NSSSECURITYWARNINGDIALOGS_CID \
+{ \
+ /* 1f5eac0a-d7e3-4f8e-b4d5-7240f7cba269 */ \
+ 0x1f5eac0a, \
+ 0xd7e3, \
+ 0x4f8e, \
+ { 0xb4, 0xd5, 0x72, 0x40, 0xf7, 0xcb, 0xa2, 0x69 } \
+}
+
+class GtkNSSSecurityWarningDialogs : public nsISecurityWarningDialogs
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISECURITYWARNINGDIALOGS
+
+ GtkNSSSecurityWarningDialogs();
+ virtual ~GtkNSSSecurityWarningDialogs();
+
+protected:
+ void DoDialog (nsIInterfaceRequestor *aContext,
+ const char *aPrefName,
+ GtkMessageType aType,
+ GtkButtonsType aButtons,
+ int aDefaultResponse,
+ const char *aTitle,
+ const char *aPrimary,
+ const char *aSecondary,
+ const char *aButtonText,
+ PRBool *_retval);
+};
+
+#endif /* !GTK_NSSSECURITYDIALOGS_H */
diff --git a/embed/xulrunner/embed/Makefile.am b/embed/xulrunner/embed/Makefile.am
new file mode 100644
index 000000000..ded6802e7
--- /dev/null
+++ b/embed/xulrunner/embed/Makefile.am
@@ -0,0 +1,159 @@
+noinst_LTLIBRARIES = libephyxulrunnerembed.la
+
+libephyxulrunnerembed_la_SOURCES = \
+ AutoJSContextStack.cpp \
+ AutoJSContextStack.h \
+ AutoWindowModalState.cpp \
+ AutoWindowModalState.h \
+ ContentHandler.cpp \
+ ContentHandler.h \
+ EphyAboutModule.cpp \
+ EphyAboutModule.h \
+ EphyBadCertRejector.cpp \
+ EphyBadCertRejector.h \
+ EphyContentPolicy.cpp \
+ EphyContentPolicy.h \
+ EphyDirectoryProvider.cpp \
+ EphyDirectoryProvider.h \
+ EphyHeaderSniffer.cpp \
+ EphyHeaderSniffer.h \
+ EphyBrowser.cpp \
+ EphyBrowser.h \
+ EphyFind.cpp \
+ EphyFind.h \
+ EphyHistoryListener.cpp \
+ EphyHistoryListener.h \
+ EphyPromptService.cpp \
+ EphyPromptService.h \
+ EphyRedirectChannel.cpp \
+ EphyRedirectChannel.h \
+ EphySidebar.cpp \
+ EphySidebar.h \
+ EphySingle.cpp \
+ EphySingle.h \
+ EphyUtils.cpp \
+ EphyUtils.h \
+ EventContext.cpp \
+ EventContext.h \
+ GeckoCookiePromptService.cpp \
+ GeckoCookiePromptService.h \
+ GeckoFormSigningDialog.cpp \
+ GeckoFormSigningDialog.h \
+ GeckoPrintService.cpp \
+ GeckoPrintService.h \
+ GeckoPrintSession.cpp \
+ GeckoPrintSession.h \
+ GlobalHistory.cpp \
+ GlobalHistory.h \
+ MozDownload.cpp \
+ MozDownload.h \
+ MozRegisterComponents.cpp \
+ MozRegisterComponents.h \
+ mozilla-download.cpp \
+ mozilla-download.h \
+ mozilla-embed.cpp \
+ mozilla-embed.h \
+ mozilla-embed-event.cpp \
+ mozilla-embed-event.h \
+ mozilla-embed-find.cpp \
+ mozilla-embed-find.h \
+ mozilla-embed-persist.cpp \
+ mozilla-embed-persist.h \
+ mozilla-embed-single.cpp \
+ mozilla-embed-single.h \
+ mozilla-notifiers.cpp \
+ mozilla-notifiers.h
+
+if ENABLE_FILEPICKER
+libephyxulrunnerembed_la_SOURCES += \
+ FilePicker.cpp \
+ FilePicker.h
+endif
+
+if HAVE_MOZILLA_PSM
+libephyxulrunnerembed_la_SOURCES += \
+ GtkNSSClientAuthDialogs.cpp \
+ GtkNSSClientAuthDialogs.h \
+ GtkNSSDialogs.cpp \
+ GtkNSSDialogs.h \
+ GtkNSSKeyPairDialogs.cpp \
+ GtkNSSKeyPairDialogs.h \
+ GtkNSSSecurityWarningDialogs.cpp\
+ GtkNSSSecurityWarningDialogs.h
+endif
+
+if ENABLE_CERTIFICATE_MANAGER
+libephyxulrunnerembed_la_SOURCES += \
+ mozilla-x509-cert.cpp \
+ mozilla-x509-cert.h
+endif
+
+if ENABLE_SPELLCHECKER
+libephyxulrunnerembed_la_SOURCES += \
+ GeckoSpellCheckEngine.cpp \
+ GeckoSpellCheckEngine.h
+endif
+
+mozilla_include_subdirs = \
+ . \
+ caps \
+ chardet \
+ chrome \
+ commandhandler \
+ content \
+ cookie \
+ docshell \
+ dom \
+ exthandler \
+ fastfind \
+ helperAppDlg \
+ find \
+ gfx \
+ gtkembedmoz \
+ history \
+ js \
+ layout \
+ locale \
+ mimetype \
+ necko \
+ nkcache \
+ passwordmgr \
+ pipboot \
+ pipnss \
+ pref \
+ shistory \
+ sidebar \
+ spellchecker \
+ uriloader \
+ uconv \
+ wallet \
+ webbrowserpersist \
+ webbrwsr \
+ widget \
+ windowwatcher \
+ xmlextras \
+ xpcom \
+ xpconnect
+
+libephyxulrunnerembed_la_CPPFLAGS = \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/embed \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/embed/gecko/src \
+ -I$(top_builddir)/embed/gecko/src \
+ -DSHARE_DIR=\"$(pkgdatadir)\" \
+ -DPLUGINDIR=\"$(libdir)/epiphany/$(EPIPHANY_MAJOR)/plugins\" \
+ -DMOZILLA_HOME=\"$(LIBXUL_LIBDIR)\" \
+ -DMOZILLA_PREFIX=\"$(LIBXUL_PREFIX)\" \
+ -DMOZILLA_NATIVE_PLUGINSDIR=\"$(libdir)/mozilla/plugins\" \
+ -DUA_VERSION=\"$(EPIPHANY_UA_VERSION)\" \
+ -DALLOW_PRIVATE_API \
+ $(AM_CPPFLAGS)
+
+libephyxulrunnerembed_la_CXXFLAGS = \
+ $(LIBXUL_CFLAGS) \
+ $(DEPENDENCIES_CFLAGS) \
+ $(AM_CXXFLAGS)
+
+libephyxulrunnerembed_la_LIBADD = \
+ $(top_builddir)/embed/xulrunner/src/libgnomegeckoembed-0.0.la
diff --git a/embed/xulrunner/embed/MozDownload.cpp b/embed/xulrunner/embed/MozDownload.cpp
new file mode 100644
index 000000000..eed7adcd9
--- /dev/null
+++ b/embed/xulrunner/embed/MozDownload.cpp
@@ -0,0 +1,787 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright © 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@netscape.com>
+ *
+ * Adapted for epiphany by Marco Pesenti Gritti <marco@gnome.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib/gi18n.h>
+
+#include <nsStringAPI.h>
+
+#include <nsComponentManagerUtils.h>
+#include <nsICancelable.h>
+#include <nsIChannel.h>
+#include <nsIDOMDocument.h>
+#include <nsIFileURL.h>
+#include <nsIIOService.h>
+#include <nsILocalFile.h>
+#include <nsIMIMEInfo.h>
+#include <nsIObserver.h>
+#include <nsIRequest.h>
+#include <nsIURI.h>
+#include <nsIWritablePropertyBag2.h>
+#include <nsIWebBrowserPersist.h>
+
+#include <nsMemory.h>
+#include <nsNetError.h>
+#include <nsServiceManagerUtils.h>
+
+#include "EphyBadCertRejector.h"
+#include "EphyUtils.h"
+
+#include "eel-gconf-extensions.h"
+#include "ephy-debug.h"
+#include "ephy-file-helpers.h"
+#include "ephy-prefs.h"
+#include "mozilla-download.h"
+
+#include "MozDownload.h"
+
+/* Minimum time between progress updates */
+#define PROGRESS_RATE 500000 /* microsec */
+
+const char* const persistContractID = "@mozilla.org/embedding/browser/nsWebBrowserPersist;1";
+
+MozDownload::MozDownload() :
+ mTotalProgress(-1),
+ mCurrentProgress(0),
+ mMaxSize(-1),
+ mStatus(NS_OK),
+ mEmbedPersist(nsnull),
+ mDownloadState(EPHY_DOWNLOAD_INITIALISING)
+{
+ LOG ("MozDownload ctor (%p)", (void *) this);
+}
+
+MozDownload::~MozDownload()
+{
+ LOG ("MozDownload dtor (%p)", (void *) this);
+
+ NS_ASSERTION (!mEphyDownload, "MozillaDownload still alive!");
+}
+
+NS_IMPL_ISUPPORTS4 (MozDownload,
+ nsIWebProgressListener,
+ nsIWebProgressListener2,
+ nsITransfer,
+ nsIInterfaceRequestor)
+
+nsresult
+MozDownload::InitForEmbed (nsIURI *aSource, nsIURI *aTarget, const nsAString &aDisplayName,
+ nsIMIMEInfo *aMIMEInfo, PRTime aStartTime, nsILocalFile *aTempFile,
+ nsICancelable *aCancelable, MozillaEmbedPersist *aEmbedPersist,
+ PRInt64 aMaxSize)
+{
+ mEmbedPersist = aEmbedPersist;
+ mMaxSize = aMaxSize;
+ return Init (aSource, aTarget, aDisplayName, aMIMEInfo, aStartTime, aTempFile, aCancelable);
+}
+
+/* void init (in nsIURI aSource, in nsIURI aTarget, in AString aDisplayName, in nsIMIMEInfo aMIMEInfo, in PRTime startTime, in nsILocalFile aTempFile, in nsICancelable aCancelable); */
+NS_IMETHODIMP
+MozDownload::Init (nsIURI *aSource,
+ nsIURI *aTarget,
+ const nsAString &aDisplayName,
+ nsIMIMEInfo *aMIMEInfo,
+ PRTime aStartTime,
+ nsILocalFile *aTempFile,
+ nsICancelable *aCancelable)
+{
+ PRBool addToView = PR_TRUE;
+
+ if (mEmbedPersist)
+ {
+ EphyEmbedPersistFlags flags;
+
+ flags = ephy_embed_persist_get_flags (EPHY_EMBED_PERSIST (mEmbedPersist));
+
+ addToView = !(flags & EPHY_EMBED_PERSIST_NO_VIEW);
+ }
+
+ mSource = aSource;
+ mDestination = aTarget;
+ mStartTime = aStartTime;
+ mTotalProgress = 0;
+ mCurrentProgress = 0;
+ mPercentComplete = 0;
+ mInterval = PROGRESS_RATE;
+ mLastUpdate = mStartTime;
+ mMIMEInfo = aMIMEInfo;
+
+ /* This will create a refcount cycle, which needs to be broken in ::OnStateChange */
+ mCancelable = aCancelable;
+
+ if (addToView)
+ {
+ DownloaderView *dview;
+ dview = EPHY_DOWNLOADER_VIEW
+ (ephy_embed_shell_get_downloader_view (embed_shell));
+ mEphyDownload = mozilla_download_new (this);
+ g_object_add_weak_pointer (G_OBJECT (mEphyDownload),
+ (gpointer *) &mEphyDownload);
+ downloader_view_add_download (dview, mEphyDownload);
+ g_object_unref (mEphyDownload);
+ }
+ else
+ {
+ mEphyDownload = nsnull;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MozDownload::GetSource(nsIURI **aSource)
+{
+ NS_ENSURE_ARG_POINTER(aSource);
+ NS_IF_ADDREF(*aSource = mSource);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MozDownload::GetTargetFile (nsILocalFile** aTargetFile)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mDestination, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsIFile> file;
+ rv = fileURL->GetFile(getter_AddRefs(file));
+ if (NS_SUCCEEDED(rv))
+ rv = CallQueryInterface(file, aTargetFile);
+ return rv;
+}
+
+NS_IMETHODIMP
+MozDownload::GetPercentComplete(PRInt32 *aPercentComplete)
+{
+ NS_ENSURE_ARG_POINTER(aPercentComplete);
+ *aPercentComplete = mPercentComplete;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MozDownload::GetTotalProgress(PRInt64 *aTotalProgress)
+{
+ NS_ENSURE_ARG_POINTER(aTotalProgress);
+ *aTotalProgress = mTotalProgress;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MozDownload::GetCurrentProgress(PRInt64 *aCurrentProgress)
+{
+ NS_ENSURE_ARG_POINTER(aCurrentProgress);
+ *aCurrentProgress = mCurrentProgress;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MozDownload::GetState(EphyDownloadState *aDownloadState)
+{
+ NS_ENSURE_ARG_POINTER(aDownloadState);
+ *aDownloadState = mDownloadState;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MozDownload::GetElapsedTime(PRInt64 *aElapsedTime)
+{
+ NS_ENSURE_ARG_POINTER(aElapsedTime);
+ *aElapsedTime = PR_Now() - mStartTime;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MozDownload::GetMIMEInfo(nsIMIMEInfo **aMIMEInfo)
+{
+ NS_ENSURE_ARG_POINTER(aMIMEInfo);
+ NS_IF_ADDREF(*aMIMEInfo = mMIMEInfo);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MozDownload::OnStateChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest,
+ PRUint32 aStateFlags, nsresult aStatus)
+{
+ nsresult rv;
+
+ if (NS_FAILED(aStatus) && NS_SUCCEEDED(mStatus))
+ mStatus = aStatus;
+
+ if (aStateFlags & STATE_START)
+ {
+ mDownloadState = EPHY_DOWNLOAD_DOWNLOADING;
+
+ if (mEphyDownload)
+ {
+ g_signal_emit_by_name (mEphyDownload, "changed");
+ }
+ }
+
+ /* We will get this even in the event of a cancel */
+ /* Due to a mozilla bug [https://bugzilla.mozilla.org/show_bug.cgi?id=304353],
+ * we'll only get STATE_STOP if we're driven from external app handler; elsewhere
+ * we get STATE_STOP | STATE_IS_NETWORK | STATE_IS_REQUEST. So check first if
+ * STATE_IS_REQUEST is set.
+ */
+ /* Be careful that download is only completed when STATE_IS_NETWORK is set
+ * and many lonely STOP events may be triggered before.
+ */
+#ifdef GNOME_ENABLE_DEBUG
+{
+ nsCString spec;
+ if (mSource) mSource->GetSpec(spec);
+
+ LOG ("url %s, status %x, state %x (is-stop:%s, is-network:%s, is-request:%s)",
+ spec.get(), aStatus, aStateFlags,
+ aStateFlags & STATE_STOP ? "t" : "f",
+ aStateFlags & STATE_IS_NETWORK ? "t" : "f",
+ aStateFlags & STATE_IS_REQUEST ? "t" : "f");
+}
+#endif
+
+ if (((aStateFlags & STATE_IS_REQUEST) &&
+ (aStateFlags & STATE_IS_NETWORK) &&
+ (aStateFlags & STATE_STOP)) ||
+ aStateFlags == STATE_STOP)
+ {
+ LOG ("STATE_STOP");
+
+ /* Keep us alive */
+ nsCOMPtr<nsITransfer> kungFuDeathGrip(this);
+
+ mDownloadState = NS_SUCCEEDED (aStatus) ? EPHY_DOWNLOAD_COMPLETED : EPHY_DOWNLOAD_FAILED;
+ if (mEphyDownload)
+ {
+ g_signal_emit_by_name (mEphyDownload, "changed");
+ }
+
+ /* break refcount cycle */
+ mCancelable = nsnull;
+
+ if (mEmbedPersist)
+ {
+ if (NS_SUCCEEDED (aStatus))
+ {
+ mozilla_embed_persist_completed (mEmbedPersist);
+ }
+ else
+ {
+ mozilla_embed_persist_cancelled (mEmbedPersist);
+ }
+ }
+ else if (NS_SUCCEEDED (aStatus))
+ {
+ /* see http://bugzilla.gnome.org/show_bug.cgi?id=456945 */
+#ifdef HAVE_GECKO_1_9
+ return NS_OK;
+#else
+ GnomeVFSMimeApplication *helperApp;
+ nsCString mimeType;
+ rv = mMIMEInfo->GetMIMEType (mimeType);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ nsString description;
+ mMIMEInfo->GetApplicationDescription (description);
+
+ nsCString cDesc;
+ NS_UTF16ToCString (description, NS_CSTRING_ENCODING_UTF8, cDesc);
+
+ /* HACK we use the application description to decide
+ if we have to open the saved file */
+ if (g_str_has_prefix (cDesc.get(), "gnome-default:"))
+ {
+ /* Format gnome-default:<usertime>:<helperapp id> */
+ char **str = g_strsplit (cDesc.get(), ":", -1);
+ g_return_val_if_fail (g_strv_length (str) == 3, NS_ERROR_FAILURE);
+
+ char *end;
+ guint32 user_time = strtoul (str[1], &end, 0);
+
+ helperApp = gnome_vfs_mime_application_new_from_desktop_id (str[2]);
+ if (!helperApp) return NS_ERROR_FAILURE;
+
+ nsCString aDest;
+ rv = mDestination->GetSpec (aDest);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ ephy_file_launch_application (helperApp, aDest.get (), user_time);
+
+ gnome_vfs_mime_application_free (helperApp);
+ g_strfreev (str);
+ }
+ else if (g_str_has_prefix (cDesc.get(), "gnome-browse-to-file:"))
+ {
+ /* Format gnome-browse-to-file:<usertime> */
+ char **str = g_strsplit (cDesc.get(), ":", -1);
+ g_return_val_if_fail (g_strv_length (str) == 2, NS_ERROR_FAILURE);
+
+ char *end;
+ guint32 user_time = strtoul (str[1], &end, 0);
+
+ nsCString aDest;
+ rv = mDestination->GetSpec (aDest);
+ NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
+
+ ephy_file_browse_to (aDest.get (), user_time);
+
+ g_strfreev (str);
+ }
+#endif /* HAVE_GECKO_1_9 */
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MozDownload::OnProgressChange (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRInt32 aCurSelfProgress,
+ PRInt32 aMaxSelfProgress,
+ PRInt32 aCurTotalProgress,
+ PRInt32 aMaxTotalProgress)
+{
+ return OnProgressChange64 (aWebProgress, aRequest,
+ aCurSelfProgress, aMaxSelfProgress,
+ aCurTotalProgress, aMaxTotalProgress);
+}
+
+/* void onProgressChange64 (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long long aCurSelfProgress, in long long aMaxSelfProgress, in long long aCurTotalProgress,
+ in long long aMaxTotalProgress); */
+NS_IMETHODIMP
+MozDownload::OnProgressChange64 (nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRInt64 aCurSelfProgress,
+ PRInt64 aMaxSelfProgress,
+ PRInt64 aCurTotalProgress,
+ PRInt64 aMaxTotalProgress)
+{
+ if (mMaxSize >= 0 &&
+ ((aMaxTotalProgress > 0 && mMaxSize < aMaxTotalProgress) ||
+ mMaxSize < aCurTotalProgress))
+ {
+ Cancel ();
+ }
+
+ if (!mRequest)
+ mRequest = aRequest;
+
+ PRInt64 now = PR_Now ();
+
+ if ((now - mLastUpdate < mInterval) &&
+ (aMaxTotalProgress == -1 || aCurTotalProgress < aMaxTotalProgress))
+ return NS_OK;
+
+ mLastUpdate = now;
+
+ if (aMaxTotalProgress <= 0)
+ {
+ mPercentComplete = -1;
+ }
+ else
+ {
+ /* Make sure not to round up, so we don't display 100% unless
+ * it's really finished!
+ */
+ mPercentComplete = (PRInt32)(((float)aCurTotalProgress / (float)aMaxTotalProgress) * 100.0);
+ }
+
+ mTotalProgress = aMaxTotalProgress;
+ mCurrentProgress = aCurTotalProgress;
+
+ if (mEphyDownload)
+ {
+ g_signal_emit_by_name (mEphyDownload, "changed");
+ }
+
+ return NS_OK;
+}
+
+#ifdef HAVE_GECKO_1_9
+/* boolean onRefreshAttempted (in nsIWebProgress aWebProgress, in nsIURI aRefreshURI, in long aDelay, in boolean aSameURI); */
+NS_IMETHODIMP
+MozDownload::OnRefreshAttempted(nsIWebProgress *aWebProgress,
+ nsIURI *aUri,
+ PRInt32 aDelay,
+ PRBool aSameUri,
+ PRBool *allowRefresh)
+{
+ *allowRefresh = PR_TRUE;
+ return NS_OK;
+}
+#endif
+
+NS_IMETHODIMP
+MozDownload::OnLocationChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MozDownload::OnStatusChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest,
+ nsresult aStatus, const PRUnichar *aMessage)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MozDownload::OnSecurityChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state)
+{
+ return NS_OK;
+}
+
+/* void getInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
+NS_IMETHODIMP
+MozDownload::GetInterface(const nsIID & uuid, void * *result)
+{
+ if (uuid.Equals (NS_GET_IID (nsIBadCertListener)) &&
+ mEmbedPersist)
+ {
+ EphyEmbedPersistFlags flags;
+
+ g_object_get (mEmbedPersist, "flags", &flags, (char *) NULL);
+
+ if (flags & EPHY_EMBED_PERSIST_NO_CERTDIALOGS)
+ {
+ nsIBadCertListener *badCertRejector = new EphyBadCertRejector ();
+ if (!badCertRejector) return NS_ERROR_OUT_OF_MEMORY;
+
+ *result = badCertRejector;
+ NS_ADDREF (badCertRejector);
+
+ return NS_OK;
+ }
+ }
+
+ return NS_ERROR_NO_INTERFACE;
+}
+
+void
+MozDownload::Cancel()
+{
+ if (mDownloadState != EPHY_DOWNLOAD_DOWNLOADING &&
+ mDownloadState != EPHY_DOWNLOAD_PAUSED)
+ {
+ return;
+ }
+
+ if (mCancelable)
+ {
+ /* FIXME: error code? */
+ mCancelable->Cancel (NS_BINDING_ABORTED);
+ }
+}
+
+void
+MozDownload::Pause()
+{
+ if (mRequest)
+ {
+ mRequest->Suspend ();
+ mDownloadState = EPHY_DOWNLOAD_PAUSED;
+ }
+}
+
+void
+MozDownload::Resume()
+{
+ if (mRequest)
+ {
+ mRequest->Resume ();
+ mDownloadState = EPHY_DOWNLOAD_DOWNLOADING;
+ }
+}
+
+nsresult InitiateMozillaDownload (nsIDOMDocument *domDocument, nsIURI *sourceURI,
+ nsILocalFile* inDestFile, const char *contentType,
+ nsIURI* inOriginalURI, MozillaEmbedPersist *embedPersist,
+ nsIInputStream *postData, nsISupports *aCacheKey,
+ PRInt64 aMaxSize)
+{
+ nsresult rv = NS_OK;
+
+ EphyEmbedPersistFlags ephy_flags;
+ ephy_flags = ephy_embed_persist_get_flags (EPHY_EMBED_PERSIST (embedPersist));
+
+ if (!ephy_embed_persist_get_dest (EPHY_EMBED_PERSIST (embedPersist)))
+ {
+ nsCString cPath;
+ inDestFile->GetNativePath (cPath);
+
+ ephy_embed_persist_set_dest (EPHY_EMBED_PERSIST (embedPersist),
+ cPath.get());
+ }
+
+ PRBool isHTML = (contentType &&
+ (strcmp (contentType, "text/html") == 0 ||
+ strcmp (contentType, "text/xml") == 0 ||
+ strcmp (contentType, "application/xhtml+xml") == 0));
+
+ nsCOMPtr<nsIWebBrowserPersist> webPersist (do_CreateInstance(persistContractID, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ PRInt64 timeNow = PR_Now();
+
+ nsString fileDisplayName;
+ inDestFile->GetLeafName(fileDisplayName);
+
+ nsCOMPtr<nsIIOService> ioService;
+ rv = EphyUtils::GetIOService (getter_AddRefs (ioService));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIURI> destURI;
+ ioService->NewFileURI (inDestFile, getter_AddRefs(destURI));
+
+ MozDownload *downloader = new MozDownload ();
+ /* dlListener attaches to its progress dialog here, which gains ownership */
+ /* FIXME is that still true? */
+ rv = downloader->InitForEmbed (inOriginalURI, destURI, fileDisplayName,
+ nsnull, timeNow, nsnull, webPersist, embedPersist, aMaxSize);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = webPersist->SetProgressListener (downloader);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ PRInt32 flags = nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES;
+
+ if (!domDocument && !isHTML && !(ephy_flags & EPHY_EMBED_PERSIST_COPY_PAGE) &&
+ !(ephy_flags & EPHY_EMBED_PERSIST_DO_CONVERSION))
+ {
+ flags |= nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION;
+ }
+ if (ephy_flags & EPHY_EMBED_PERSIST_COPY_PAGE)
+ {
+ flags |= nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE;
+ }
+ webPersist->SetPersistFlags(flags);
+
+ /* Create a new tagged channel if we need to block cookies from server */
+ if (ephy_flags & EPHY_EMBED_PERSIST_NO_COOKIES)
+ {
+ nsCOMPtr<nsIChannel> tmpChannel;
+ rv = ioService->NewChannelFromURI (sourceURI, getter_AddRefs (tmpChannel));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(tmpChannel);
+ rv = props->SetPropertyAsBool (NS_LITERAL_STRING("epiphany-blocking-cookies"), PR_TRUE);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = webPersist->SaveChannel (tmpChannel, inDestFile);
+ }
+ else if (!domDocument || !isHTML || ephy_flags & EPHY_EMBED_PERSIST_COPY_PAGE)
+ {
+ rv = webPersist->SaveURI (sourceURI, aCacheKey, nsnull,
+ postData, nsnull, inDestFile);
+ }
+ else
+ {
+ PRInt32 encodingFlags = 0;
+ nsCOMPtr<nsILocalFile> filesFolder;
+
+ /**
+ * Construct a directory path to hold the associated files; mozilla
+ * will create the directory as needed.
+ */
+
+ nsCString cPath;
+ inDestFile->GetNativePath (cPath);
+
+ char *basename = g_path_get_basename (cPath.get());
+ char *dirname = g_path_get_dirname (cPath.get());
+ char *dot_pos = strchr (basename, '.');
+ if (dot_pos)
+ {
+ *dot_pos = 0;
+ }
+ /* translators: this is the directory name to store auxilary files when saving html files */
+ char *new_basename = g_strdup_printf (_("%s Files"), basename);
+ char *new_path = g_build_filename (dirname, new_basename, NULL);
+ g_free (new_basename);
+ g_free (basename);
+ g_free (dirname);
+
+ filesFolder = do_CreateInstance ("@mozilla.org/file/local;1");
+ filesFolder->InitWithNativePath (nsCString(new_path));
+
+ g_free (new_path);
+
+ rv = webPersist->SaveDocument (domDocument, inDestFile, filesFolder,
+ contentType, encodingFlags, 80);
+ }
+
+ return rv;
+}
+
+static char*
+GetFilePath (const char *filename)
+{
+ const char *home_dir;
+ char *download_dir, *path;
+
+ download_dir = ephy_file_get_downloads_dir ();
+
+ if (ephy_ensure_dir_exists (download_dir, NULL))
+ {
+ path = g_build_filename (download_dir, filename, (char *) NULL);
+ }
+ else
+ {
+ home_dir = g_get_home_dir ();
+ path = g_build_filename (home_dir ? home_dir : "/", filename, (char *) NULL);
+ }
+ g_free (download_dir);
+
+ return path;
+}
+
+static const char*
+file_is_compressed (const char *filename)
+{
+ int i;
+ static const char * const compression[] = {".gz", ".bz2", ".Z", ".lz", NULL};
+
+ for (i = 0; compression[i] != NULL; i++)
+ {
+ if (g_str_has_suffix (filename, compression[i]))
+ return compression[i];
+ }
+
+ return NULL;
+}
+
+static const char*
+parse_extension (const char *filename)
+{
+ const char *compression;
+
+ compression = file_is_compressed (filename);
+
+ /* If the file is compressed we might have a double extension */
+ if (compression != NULL)
+ {
+ int i;
+ static const char * const extensions[] = {"tar", "ps", "xcf", "dvi", "txt", "text", NULL};
+
+ for (i = 0; extensions[i] != NULL; i++)
+ {
+ char *suffix;
+ suffix = g_strdup_printf (".%s%s", extensions[i],
+ compression);
+
+ if (g_str_has_suffix (filename, suffix))
+ {
+ char *p;
+
+ p = g_strrstr (filename, suffix);
+ g_free (suffix);
+
+ return p;
+ }
+
+ g_free (suffix);
+ }
+ }
+
+ /* default case */
+ return g_strrstr (filename, ".");
+}
+
+nsresult BuildDownloadPath (const char *defaultFileName, nsILocalFile **_retval)
+{
+ char *path;
+
+ path = GetFilePath (defaultFileName);
+
+ if (g_file_test (path, G_FILE_TEST_EXISTS))
+ {
+ int i = 1;
+ const char *dot_pos;
+ char *serial = NULL;
+ GString *tmp_path;
+ gssize position;
+
+ dot_pos = parse_extension (defaultFileName);
+ if (dot_pos)
+ {
+ position = dot_pos - defaultFileName;
+ }
+ else
+ {
+ position = strlen (defaultFileName);
+ }
+ tmp_path = g_string_new (NULL);
+
+ do {
+ g_free (path);
+ g_string_assign (tmp_path, defaultFileName);
+ serial = g_strdup_printf ("(%d)", i++);
+ g_string_insert (tmp_path, position, serial);
+ g_free (serial);
+ path = GetFilePath (tmp_path->str);
+
+ } while (g_file_test (path, G_FILE_TEST_EXISTS));
+
+ g_string_free (tmp_path, TRUE);
+ }
+
+ nsCOMPtr <nsILocalFile> destFile (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+ NS_ENSURE_TRUE (destFile, NS_ERROR_FAILURE);
+
+ destFile->InitWithNativePath (nsCString (path));
+ g_free (path);
+
+ NS_IF_ADDREF (*_retval = destFile);
+ return NS_OK;
+}
diff --git a/embed/xulrunner/embed/MozDownload.h b/embed/xulrunner/embed/MozDownload.h
new file mode 100644
index 000000000..bf7f11e1b
--- /dev/null
+++ b/embed/xulrunner/embed/MozDownload.h
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright © 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * $Id$
+ */
+
+#ifndef MozDownload_h__
+#define MozDownload_h__
+
+#include <libgnomevfs/gnome-vfs-mime-handlers.h>
+
+#include <nsCOMPtr.h>
+#include <nsIInterfaceRequestor.h>
+#include <nsITransfer.h>
+#include <nsIWebProgressListener.h>
+
+#include "mozilla-embed-persist.h"
+#include "downloader-view.h"
+#include "ephy-download.h"
+#include "ephy-embed-shell.h"
+
+class nsICancelable;
+class nsIDOMDocument;
+class nsIInputStream;
+class nsILocalFile;
+class nsIMIMEInfo;
+class nsIObserver;
+class nsIRequest;
+class nsIURI;
+class nsIWebBrowserPersist;
+
+/* MozDownload
+ Holds information used to display a single download in the UI. This object is
+ created in one of two ways:
+ (1) By nsExternalHelperAppHandler when Gecko encounters a MIME type which
+ it doesn't itself handle. In this case, the notifications sent to
+ nsIDownload are controlled by nsExternalHelperAppHandler.
+ (2) By the embedding app's file saving code when saving a web page or a link
+ target. See CHeaderSniffer.cpp. In this case, the notifications sent to
+ nsIDownload are controlled by the implementation of nsIWebBrowserPersist.
+*/
+
+#define MOZ_DOWNLOAD_CID \
+{ /* d2a2f743-f126-4f1f-1234-d4e50490f112 */ \
+ 0xd2a2f743, \
+ 0xf126, \
+ 0x4f1f, \
+ {0x12, 0x34, 0xd4, 0xe5, 0x04, 0x90, 0xf1, 0x12} \
+}
+
+#define MOZ_DOWNLOAD_CLASSNAME "Ephy's Download Progress Dialog"
+
+nsresult InitiateMozillaDownload (nsIDOMDocument *domDocument, nsIURI *sourceUri,
+ nsILocalFile* inDestFile, const char *contentType,
+ nsIURI* inOriginalURI, MozillaEmbedPersist *embedPersist,
+ nsIInputStream *postData, nsISupports *aCacheKey,
+ PRInt64 aMaxSize);
+nsresult BuildDownloadPath (const char *defaultFileName, nsILocalFile **_retval);
+
+class MozDownload : public nsITransfer,
+ public nsIInterfaceRequestor
+{
+public:
+ MozDownload();
+ virtual ~MozDownload();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIWEBPROGRESSLISTENER
+ NS_DECL_NSIWEBPROGRESSLISTENER2
+ NS_DECL_NSITRANSFER
+ NS_DECL_NSIINTERFACEREQUESTOR
+
+ nsresult GetMIMEInfo (nsIMIMEInfo **aMIMEInfo);
+ nsresult GetTargetFile (nsILocalFile **aFile);
+ nsresult GetSource(nsIURI * *aSource);
+ nsresult GetPercentComplete(PRInt32 *aPercentComplete);
+
+ virtual void Cancel();
+ virtual void Pause();
+ virtual void Resume();
+
+ nsresult GetState (EphyDownloadState *aDownloadState);
+ nsresult GetCurrentProgress (PRInt64 *aCurrentProgress);
+ nsresult GetTotalProgress (PRInt64 *aTProgress);
+ nsresult GetElapsedTime (PRInt64 *aTProgress);
+
+ nsresult InitForEmbed (nsIURI *aSource, nsIURI *aTarget,
+ const nsAString &aDisplayName, nsIMIMEInfo *aMIMEInfo,
+ PRTime aStartTime, nsILocalFile *aTempFile,
+ nsICancelable *aCancelable, MozillaEmbedPersist *aEmbedPersist,
+ PRInt64 aMaxSize);
+
+protected:
+ nsCOMPtr<nsIURI> mSource;
+ nsCOMPtr<nsIURI> mDestination;
+
+ nsCOMPtr<nsIMIMEInfo> mMIMEInfo;
+ PRTime mStartTime;
+ PRTime mLastUpdate;
+ PRInt64 mElapsed;
+ PRInt32 mInterval;
+ PRInt32 mPercentComplete;
+ PRInt64 mTotalProgress;
+ PRInt64 mCurrentProgress;
+ PRInt64 mMaxSize;
+
+ nsresult mStatus;
+
+ nsCOMPtr<nsICancelable> mCancelable;
+ nsCOMPtr<nsIRequest> mRequest;
+ EphyDownload *mEphyDownload;
+ DownloaderView *mDownloaderView;
+ MozillaEmbedPersist *mEmbedPersist;
+ EphyDownloadState mDownloadState;
+};
+
+#endif // MozDownload_h__
diff --git a/embed/xulrunner/embed/MozRegisterComponents.cpp b/embed/xulrunner/embed/MozRegisterComponents.cpp
new file mode 100644
index 000000000..e712bbc5d
--- /dev/null
+++ b/embed/xulrunner/embed/MozRegisterComponents.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright © 2001,2002,2003 Philip Langdale
+ * Copyright © 2003 Marco Pesenti Gritti
+ * Copyright © 2004, 2005, 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib/gmessages.h>
+
+#include <nsStringAPI.h>
+
+#include <nsComponentManagerUtils.h>
+#include <nsCOMPtr.h>
+#include <nsCURILoader.h>
+#include <nsDocShellCID.h>
+#include <nsICategoryManager.h>
+#include <nsIComponentManager.h>
+#include <nsIComponentRegistrar.h>
+#include <nsIGenericFactory.h>
+#include <nsILocalFile.h>
+#include <nsIScriptNameSpaceManager.h>
+#include <nsIServiceManager.h>
+#include <nsMemory.h>
+#include <nsNetCID.h>
+#include <nsServiceManagerUtils.h>
+
+#ifdef HAVE_GECKO_1_9
+#include <nsIClassInfoImpl.h>
+#endif
+
+#ifdef HAVE_MOZILLA_PSM
+#include <nsISecureBrowserUI.h>
+#endif
+
+#include "ContentHandler.h"
+#include "EphyAboutModule.h"
+#include "EphyContentPolicy.h"
+#include "EphyPromptService.h"
+#include "EphySidebar.h"
+#include "GeckoCookiePromptService.h"
+#include "GeckoPrintService.h"
+#include "GeckoPrintSession.h"
+#include "GlobalHistory.h"
+#include "MozDownload.h"
+
+#ifdef ENABLE_FILEPICKER
+#include "FilePicker.h"
+#endif
+
+#ifdef ENABLE_SPELLCHECKER
+#include "GeckoSpellCheckEngine.h"
+#endif
+
+#ifdef HAVE_MOZILLA_PSM
+#include "GtkNSSClientAuthDialogs.h"
+#include "GtkNSSDialogs.h"
+#include "GtkNSSKeyPairDialogs.h"
+#include "GtkNSSSecurityWarningDialogs.h"
+#include "GeckoFormSigningDialog.h"
+#endif
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(EphyAboutModule)
+NS_GENERIC_FACTORY_CONSTRUCTOR(EphyContentPolicy)
+NS_GENERIC_FACTORY_CONSTRUCTOR(EphyPromptService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(EphySidebar)
+NS_GENERIC_FACTORY_CONSTRUCTOR(GContentHandler)
+NS_GENERIC_FACTORY_CONSTRUCTOR(GeckoCookiePromptService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(GeckoPrintService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(GeckoPrintSession)
+NS_GENERIC_FACTORY_CONSTRUCTOR(MozDownload)
+NS_GENERIC_FACTORY_CONSTRUCTOR(MozGlobalHistory)
+
+#ifdef ENABLE_FILEPICKER
+NS_GENERIC_FACTORY_CONSTRUCTOR(GFilePicker)
+#endif
+
+#ifdef ENABLE_SPELLCHECKER
+NS_GENERIC_FACTORY_CONSTRUCTOR(GeckoSpellCheckEngine)
+#endif
+
+#ifdef HAVE_MOZILLA_PSM
+NS_GENERIC_FACTORY_CONSTRUCTOR(GtkNSSClientAuthDialogs)
+NS_GENERIC_FACTORY_CONSTRUCTOR(GtkNSSDialogs)
+NS_GENERIC_FACTORY_CONSTRUCTOR(GtkNSSKeyPairDialogs)
+NS_GENERIC_FACTORY_CONSTRUCTOR(GtkNSSSecurityWarningDialogs)
+NS_GENERIC_FACTORY_CONSTRUCTOR(GeckoFormSigningDialog)
+#endif
+
+#define XPINSTALL_CONTRACTID NS_CONTENT_HANDLER_CONTRACTID_PREFIX "application/x-xpinstall"
+
+/* class information */
+NS_DECL_CLASSINFO(EphySidebar)
+
+/* FIXME: uninstall XPI handler */
+
+static const nsModuleComponentInfo sAppComps[] = {
+ {
+ MOZ_DOWNLOAD_CLASSNAME,
+ MOZ_DOWNLOAD_CID,
+#ifdef NS_TRANSFER_CONTRACTID
+ NS_TRANSFER_CONTRACTID,
+#else
+ NS_DOWNLOAD_CONTRACTID,
+#endif
+ MozDownloadConstructor
+ },
+#ifdef ENABLE_FILEPICKER
+ {
+ G_FILEPICKER_CLASSNAME,
+ G_FILEPICKER_CID,
+ G_FILEPICKER_CONTRACTID,
+ GFilePickerConstructor
+ },
+#endif
+#ifdef HAVE_MOZILLA_PSM
+ {
+ GTK_NSSCLIENTAUTHDIALOGS_CLASSNAME,
+ GTK_NSSCLIENTAUTHDIALOGS_CID,
+ NS_CLIENTAUTHDIALOGS_CONTRACTID,
+ GtkNSSClientAuthDialogsConstructor
+ },
+ {
+ GTK_NSSDIALOGS_CLASSNAME,
+ GTK_NSSDIALOGS_CID,
+ NS_BADCERTLISTENER_CONTRACTID,
+ GtkNSSDialogsConstructor
+ },
+ {
+ GTK_NSSDIALOGS_CLASSNAME,
+ GTK_NSSDIALOGS_CID,
+ NS_CERTIFICATEDIALOGS_CONTRACTID,
+ GtkNSSDialogsConstructor
+ },
+ {
+ GTK_NSSDIALOGS_CLASSNAME,
+ GTK_NSSDIALOGS_CID,
+ NS_DOMCRYPTODIALOGS_CONTRACTID,
+ GtkNSSDialogsConstructor
+ },
+ {
+ GTK_NSSDIALOGS_CLASSNAME,
+ GTK_NSSDIALOGS_CID,
+ NS_TOKENDIALOGS_CONTRACTID,
+ GtkNSSDialogsConstructor
+ },
+ {
+ GTK_NSSDIALOGS_CLASSNAME,
+ GTK_NSSDIALOGS_CID,
+ NS_TOKENPASSWORDSDIALOG_CONTRACTID,
+ GtkNSSDialogsConstructor
+ },
+ {
+ GTK_NSSKEYPAIRDIALOGS_CLASSNAME,
+ GTK_NSSKEYPAIRDIALOGS_CID,
+ NS_GENERATINGKEYPAIRINFODIALOGS_CONTRACTID,
+ GtkNSSKeyPairDialogsConstructor
+ },
+ {
+ GTK_NSSSECURITYWARNINGDIALOGS_CLASSNAME,
+ GTK_NSSSECURITYWARNINGDIALOGS_CID,
+ NS_SECURITYWARNINGDIALOGS_CONTRACTID,
+ GtkNSSSecurityWarningDialogsConstructor
+ },
+ {
+ GECKO_FORMSIGNINGDIALOGS_CLASSNAME,
+ GECKO_FORMSIGNINGDIALOGS_CID,
+ NS_FORMSIGNINGDIALOG_CONTRACTID,
+ GeckoFormSigningDialogConstructor
+ },
+#endif /* HAVE_MOZILLA_PSM */
+ {
+ NS_IHELPERAPPLAUNCHERDLG_CLASSNAME,
+ G_CONTENTHANDLER_CID,
+ NS_IHELPERAPPLAUNCHERDLG_CONTRACTID,
+ GContentHandlerConstructor
+ },
+ {
+ EPHY_GLOBALHISTORY_CLASSNAME,
+ EPHY_GLOBALHISTORY_CID,
+ NS_GLOBALHISTORY2_CONTRACTID,
+ MozGlobalHistoryConstructor
+ },
+ {
+ GECKO_PRINT_SERVICE_CLASSNAME,
+ GECKO_PRINT_SERVICE_IID,
+ "@mozilla.org/embedcomp/printingprompt-service;1",
+ GeckoPrintServiceConstructor
+ },
+ {
+ GECKO_PRINT_SESSION_CLASSNAME,
+ GECKO_PRINT_SESSION_IID,
+ "@mozilla.org/gfx/printsession;1",
+ GeckoPrintSessionConstructor
+ },
+ {
+ EPHY_CONTENT_POLICY_CLASSNAME,
+ EPHY_CONTENT_POLICY_CID,
+ EPHY_CONTENT_POLICY_CONTRACTID,
+ EphyContentPolicyConstructor,
+ EphyContentPolicy::Register,
+ EphyContentPolicy::Unregister
+ },
+ {
+ EPHY_SIDEBAR_CLASSNAME,
+ EPHY_SIDEBAR_CID,
+ NS_SIDEBAR_CONTRACTID,
+ EphySidebarConstructor,
+ EphySidebar::Register,
+ EphySidebar::Unregister,
+ nsnull /* no factory destructor */,
+ NS_CI_INTERFACE_GETTER_NAME(EphySidebar),
+ nsnull /* no language helper */,
+ &NS_CLASSINFO_NAME(EphySidebar),
+ nsIClassInfo::DOM_OBJECT
+ },
+ {
+ EPHY_ABOUT_EPIPHANY_CLASSNAME,
+ EPHY_ABOUT_MODULE_CID,
+ EPHY_ABOUT_EPIPHANY_CONTRACTID,
+ EphyAboutModuleConstructor
+ },
+ {
+ EPHY_ABOUT_RECOVER_CLASSNAME,
+ EPHY_ABOUT_MODULE_CID,
+ EPHY_ABOUT_RECOVER_CONTRACTID,
+ EphyAboutModuleConstructor
+ },
+ {
+ EPHY_ABOUT_NETERROR_CLASSNAME,
+ EPHY_ABOUT_MODULE_CID,
+ EPHY_ABOUT_NETERROR_CONTRACTID,
+ EphyAboutModuleConstructor
+ },
+ {
+ EPHY_PROMPT_SERVICE_CLASSNAME,
+ EPHY_PROMPT_SERVICE_IID,
+ "@mozilla.org/embedcomp/prompt-service;1",
+ EphyPromptServiceConstructor
+ },
+#ifdef HAVE_NSINONBLOCKINGALERTSERVICE_H
+ {
+ EPHY_PROMPT_SERVICE_CLASSNAME,
+ EPHY_PROMPT_SERVICE_IID,
+ "@mozilla.org/embedcomp/nbalert-service;1",
+ EphyPromptServiceConstructor
+ },
+#endif /* HAVE_NSINONBLOCKINGALERTSERVICE_H */
+#ifdef ENABLE_SPELLCHECKER
+ {
+ GECKO_SPELL_CHECK_ENGINE_CLASSNAME,
+ GECKO_SPELL_CHECK_ENGINE_IID,
+ GECKO_SPELL_CHECK_ENGINE_CONTRACTID,
+ GeckoSpellCheckEngineConstructor
+ },
+#endif /* ENABLE_SPELLCHECK */
+ {
+ EPHY_COOKIEPROMPTSERVICE_CLASSNAME,
+ EPHY_COOKIEPROMPTSERVICE_CID,
+ EPHY_COOKIEPROMPTSERVICE_CONTRACTID,
+ GeckoCookiePromptServiceConstructor
+ }
+};
+
+gboolean
+mozilla_register_components (void)
+{
+ gboolean ret = TRUE;
+ nsresult rv;
+
+ nsCOMPtr<nsIComponentRegistrar> cr;
+ NS_GetComponentRegistrar(getter_AddRefs(cr));
+ NS_ENSURE_TRUE (cr, FALSE);
+
+ nsCOMPtr<nsIComponentManager> cm;
+ NS_GetComponentManager (getter_AddRefs (cm));
+ NS_ENSURE_TRUE (cm, FALSE);
+
+ for (guint i = 0; i < G_N_ELEMENTS (sAppComps); i++)
+ {
+ nsCOMPtr<nsIGenericFactory> componentFactory;
+ rv = NS_NewGenericFactory(getter_AddRefs(componentFactory),
+ &(sAppComps[i]));
+ if (NS_FAILED(rv) || !componentFactory)
+ {
+ g_warning ("Failed to make a factory for %s\n", sAppComps[i].mDescription);
+
+ ret = FALSE;
+ continue; // don't abort registering other components
+ }
+
+ rv = cr->RegisterFactory(sAppComps[i].mCID,
+ sAppComps[i].mDescription,
+ sAppComps[i].mContractID,
+ componentFactory);
+ if (NS_FAILED(rv))
+ {
+ g_warning ("Failed to register %s\n", sAppComps[i].mDescription);
+
+ ret = FALSE;
+ }
+
+ if (sAppComps[i].mRegisterSelfProc)
+ {
+ rv = sAppComps[i].mRegisterSelfProc (cm, nsnull, nsnull, nsnull, &sAppComps[i]);
+
+ if (NS_FAILED (rv))
+ {
+ g_warning ("Failed to register-self for %s\n", sAppComps[i].mDescription);
+ ret = FALSE;
+ }
+ }
+ }
+
+ return ret;
+}
diff --git a/embed/xulrunner/embed/MozRegisterComponents.h b/embed/xulrunner/embed/MozRegisterComponents.h
new file mode 100644
index 000000000..e8e086f3b
--- /dev/null
+++ b/embed/xulrunner/embed/MozRegisterComponents.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2001 Philip Langdale
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef MOZREGISTERCOMPONENTS_H
+#define MOZREGISTERCOMPONENTS_H
+
+#include <glib.h>
+
+gboolean mozilla_register_components (void);
+
+#endif /* MOZREGISTERCOMPONENTS_H */
diff --git a/embed/xulrunner/embed/mozilla-download.cpp b/embed/xulrunner/embed/mozilla-download.cpp
new file mode 100644
index 000000000..0b420547c
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-download.cpp
@@ -0,0 +1,313 @@
+/*
+ * Copyright © 2003 Xan Lopez
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <nsStringAPI.h>
+
+#include <nsILocalFile.h>
+#include <nsIMIMEInfo.h>
+#include <nsIURI.h>
+#include <nsMemory.h>
+
+#include "ephy-debug.h"
+
+#include "MozDownload.h"
+
+#include "mozilla-download.h"
+
+static void mozilla_download_class_init (MozillaDownloadClass *klass);
+static void mozilla_download_init (MozillaDownload *ges);
+static void mozilla_download_finalize (GObject *object);
+
+enum
+{
+ PROP_0,
+ PROP_MOZDOWNLOAD
+};
+
+struct _MozillaDownloadPrivate
+{
+ MozDownload *moz_download;
+};
+
+#define MOZILLA_DOWNLOAD_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), MOZILLA_TYPE_DOWNLOAD, MozillaDownloadPrivate))
+
+static GObjectClass *parent_class = NULL;
+
+GType
+mozilla_download_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ const GTypeInfo our_info =
+ {
+ sizeof (MozillaDownloadClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) mozilla_download_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (MozillaDownload),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mozilla_download_init
+ };
+
+ type = g_type_register_static (EPHY_TYPE_DOWNLOAD,
+ "MozillaDownload",
+ &our_info, (GTypeFlags)0);
+ }
+
+ return type;
+}
+
+static char *
+impl_get_target (EphyDownload *download)
+{
+ nsCOMPtr<nsILocalFile> targetFile;
+ MozDownload *mozDownload;
+
+ mozDownload = MOZILLA_DOWNLOAD (download)->priv->moz_download;
+
+ mozDownload->GetTargetFile (getter_AddRefs (targetFile));
+
+ nsCString tempPathStr;
+ targetFile->GetNativePath (tempPathStr);
+
+ return g_strdup (tempPathStr.get ());
+}
+
+static char *
+impl_get_source (EphyDownload *download)
+{
+ nsCOMPtr<nsIURI> uri;
+ MozDownload *mozDownload;
+ nsCString spec;
+
+ mozDownload = MOZILLA_DOWNLOAD (download)->priv->moz_download;
+
+ mozDownload->GetSource (getter_AddRefs (uri));
+ uri->GetSpec (spec);
+
+ return g_strdup (spec.get());
+}
+
+static gint64
+impl_get_current_progress (EphyDownload *download)
+{
+ MozDownload *mozDownload;
+ PRInt64 progress;
+
+ mozDownload = MOZILLA_DOWNLOAD (download)->priv->moz_download;
+
+ mozDownload->GetCurrentProgress (&progress);
+
+ return progress;
+}
+
+static EphyDownloadState
+impl_get_state (EphyDownload *download)
+{
+ MozDownload *mozDownload;
+ EphyDownloadState state;
+
+ mozDownload = MOZILLA_DOWNLOAD (download)->priv->moz_download;
+
+ mozDownload->GetState (&state);
+
+ return state;
+}
+
+static gint64
+impl_get_total_progress (EphyDownload *download)
+{
+ MozDownload *mozDownload;
+ PRInt64 progress;
+
+ mozDownload = MOZILLA_DOWNLOAD (download)->priv->moz_download;
+
+ mozDownload->GetTotalProgress (&progress);
+
+ return progress;
+}
+
+static int
+impl_get_percent (EphyDownload *download)
+{
+ MozDownload *mozDownload;
+ PRInt32 percent;
+
+ mozDownload = MOZILLA_DOWNLOAD (download)->priv->moz_download;
+
+ mozDownload->GetPercentComplete (&percent);
+
+ return percent;
+}
+
+static gint64
+impl_get_elapsed_time (EphyDownload *download)
+{
+ MozDownload *mozDownload;
+ PRInt64 elapsed;
+
+ mozDownload = MOZILLA_DOWNLOAD (download)->priv->moz_download;
+
+ mozDownload->GetElapsedTime (&elapsed);
+
+ return elapsed / 1000000;
+}
+
+static char*
+impl_get_mime (EphyDownload *download)
+{
+ MozDownload *mozDownload;
+ nsCOMPtr<nsIMIMEInfo> mime;
+ nsCString mimeType;
+
+ mozDownload = MOZILLA_DOWNLOAD (download)->priv->moz_download;
+
+ mozDownload->GetMIMEInfo (getter_AddRefs(mime));
+ if (!mime) return g_strdup ("application/octet-stream");
+
+ mime->GetMIMEType(mimeType);
+
+ return g_strdup (mimeType.get());
+}
+
+static void
+impl_cancel (EphyDownload *download)
+{
+ MOZILLA_DOWNLOAD (download)->priv->moz_download->Cancel ();
+}
+
+static void
+impl_pause (EphyDownload *download)
+{
+ MOZILLA_DOWNLOAD (download)->priv->moz_download->Pause ();
+}
+
+static void
+impl_resume (EphyDownload *download)
+{
+ MOZILLA_DOWNLOAD (download)->priv->moz_download->Resume ();
+}
+
+static void
+mozilla_download_finalize (GObject *object)
+{
+ MozillaDownload *download = MOZILLA_DOWNLOAD (object);
+
+ NS_RELEASE (download->priv->moz_download);
+
+ LOG ("MozillaDownload %p finalised", object);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+mozilla_download_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MozillaDownload *download = MOZILLA_DOWNLOAD (object);
+
+ switch (prop_id)
+ {
+ case PROP_MOZDOWNLOAD:
+ MozDownload *moz_download;
+
+ moz_download = (MozDownload *)g_value_get_pointer (value);
+ NS_ADDREF (moz_download);
+ download->priv->moz_download = moz_download;
+ break;
+ }
+}
+
+static void
+mozilla_download_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MozillaDownload *download = MOZILLA_DOWNLOAD (object);
+
+ switch (prop_id)
+ {
+ case PROP_MOZDOWNLOAD:
+ g_value_set_pointer (value, download->priv->moz_download);
+ break;
+ }
+}
+
+static void
+mozilla_download_class_init (MozillaDownloadClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ EphyDownloadClass *download_class = EPHY_DOWNLOAD_CLASS (klass);
+
+ parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
+
+ object_class->finalize = mozilla_download_finalize;
+ object_class->set_property = mozilla_download_set_property;
+ object_class->get_property = mozilla_download_get_property;
+
+ download_class->get_elapsed_time = impl_get_elapsed_time;
+ download_class->get_current_progress = impl_get_current_progress;
+ download_class->get_total_progress = impl_get_total_progress;
+ download_class->get_percent = impl_get_percent;
+ download_class->get_target = impl_get_target;
+ download_class->get_source = impl_get_source;
+ download_class->get_state = impl_get_state;
+ download_class->get_mime = impl_get_mime;
+ download_class->cancel = impl_cancel;
+ download_class->pause = impl_pause;
+ download_class->resume = impl_resume;
+
+ g_type_class_add_private (klass, sizeof (MozillaDownloadPrivate));
+
+ g_object_class_install_property (object_class,
+ PROP_MOZDOWNLOAD,
+ g_param_spec_pointer ("mozilla-download",
+ "Mozilla Download",
+ "Mozilla Download",
+ (GParamFlags)
+ (G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB |
+ G_PARAM_CONSTRUCT_ONLY)));
+}
+
+static void
+mozilla_download_init (MozillaDownload *download)
+{
+ LOG ("MozillaDownload %p initialising", download);
+
+ download->priv = MOZILLA_DOWNLOAD_GET_PRIVATE (download);
+}
+
+EphyDownload *
+mozilla_download_new (MozDownload *download)
+{
+ return EPHY_DOWNLOAD (g_object_new (MOZILLA_TYPE_DOWNLOAD,
+ "mozilla-download", download,
+ NULL));
+}
diff --git a/embed/xulrunner/embed/mozilla-download.h b/embed/xulrunner/embed/mozilla-download.h
new file mode 100644
index 000000000..071ec31af
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-download.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2000, 2001, 2002 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef MOZILLA_DOWNLOAD_H
+#define MOZILLA_DOWNLOAD_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "ephy-download.h"
+
+G_BEGIN_DECLS
+
+#define MOZILLA_TYPE_DOWNLOAD (mozilla_download_get_type ())
+#define MOZILLA_DOWNLOAD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MOZILLA_TYPE_DOWNLOAD, MozillaDownload))
+#define MOZILLA_DOWNLOAD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MOZILLA_TYPE_DOWNLOAD, MozillaDownloadClass))
+#define MOZILLA_IS_DOWNLOAD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MOZILLA_TYPE_DOWNLOAD))
+#define MOZILLA_IS_DOWNLOAD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MOZILLA_TYPE_DOWNLOAD))
+#define MOZILLA_DOWNLOAD_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MOZILLA_TYPE_DOWNLOAD, MozillaDownloadClass))
+
+typedef struct _MozillaDownloadClass MozillaDownloadClass;
+typedef struct _MozillaDownload MozillaDownload;
+typedef struct _MozillaDownloadPrivate MozillaDownloadPrivate;
+
+class MozDownload;
+
+struct _MozillaDownload
+{
+ EphyDownload parent;
+ MozillaDownloadPrivate *priv;
+};
+
+struct _MozillaDownloadClass
+{
+ EphyDownloadClass parent_class;
+};
+
+GType mozilla_download_get_type (void);
+
+EphyDownload *mozilla_download_new (MozDownload *download);
+
+G_END_DECLS
+
+#endif
diff --git a/embed/xulrunner/embed/mozilla-embed-event.cpp b/embed/xulrunner/embed/mozilla-embed-event.cpp
new file mode 100644
index 000000000..9b5b06d85
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-embed-event.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright © 2000-2003 Marco Pesenti Gritti
+ * Copyright © 2004 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <glib/ghash.h>
+
+#include <nsCOMPtr.h>
+#include <nsIDOMEvent.h>
+
+#include "ephy-debug.h"
+
+#include "mozilla-embed-event.h"
+
+#define MOZILLA_EMBED_EVENT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), MOZILLA_TYPE_EMBED_EVENT, MozillaEmbedEventPrivate))
+
+struct _MozillaEmbedEventPrivate
+{
+ nsIDOMEvent* dom_event;
+ GHashTable *props;
+};
+
+static void mozilla_embed_event_class_init (MozillaEmbedEventClass *klass);
+static void mozilla_embed_event_init (MozillaEmbedEvent *event);
+static void ephy_embed_event_iface_init (EphyEmbedEventIface *iface);
+
+static GObjectClass *parent_class = NULL;
+
+GType
+mozilla_embed_event_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ const GTypeInfo our_info =
+ {
+ sizeof (MozillaEmbedEventClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) mozilla_embed_event_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (MozillaEmbedEvent),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mozilla_embed_event_init
+ };
+
+ const GInterfaceInfo embed_event_info =
+ {
+ (GInterfaceInitFunc) ephy_embed_event_iface_init,
+ NULL,
+ NULL
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "MozillaEmbedEvent",
+ &our_info, (GTypeFlags) 0);
+
+ g_type_add_interface_static (type,
+ EPHY_TYPE_EMBED_EVENT,
+ &embed_event_info);
+ }
+
+ return type;
+}
+
+MozillaEmbedEvent *
+mozilla_embed_event_new (gpointer dom_event)
+{
+ MozillaEmbedEvent *event;
+
+ event = MOZILLA_EMBED_EVENT (g_object_new (MOZILLA_TYPE_EMBED_EVENT, NULL));
+
+ event->priv->dom_event = static_cast<nsIDOMEvent*>(dom_event);
+ NS_IF_ADDREF (event->priv->dom_event);
+
+ return event;
+}
+
+void
+mozilla_embed_event_set_property (MozillaEmbedEvent *event,
+ const char *name,
+ GValue *value)
+{
+ char *value_content = g_strdup_value_contents (value);
+ LOG ("embed event %p set property \"%s\" to %s", event, name, value_content);
+ g_free (value_content);
+
+ g_hash_table_insert (event->priv->props,
+ g_strdup (name),
+ value);
+}
+
+static EphyEmbedEventContext
+impl_get_context (EphyEmbedEvent *event)
+{
+ return (EphyEmbedEventContext) ((MozillaEmbedEvent *) event)->context;
+}
+
+static guint
+impl_get_button (EphyEmbedEvent *event)
+{
+ return ((MozillaEmbedEvent *) event)->button;
+}
+
+static guint
+impl_get_modifier (EphyEmbedEvent *event)
+{
+ return ((MozillaEmbedEvent *) event)->modifier;
+}
+
+static void
+impl_get_coordinates (EphyEmbedEvent *event,
+ guint *x,
+ guint *y)
+{
+ *x = ((MozillaEmbedEvent *) event)->x;
+ *y = ((MozillaEmbedEvent *) event)->y;
+}
+
+static const GValue*
+impl_get_property (EphyEmbedEvent *event,
+ const char *name)
+{
+ return (const GValue *) g_hash_table_lookup (((MozillaEmbedEvent *) event)->priv->props, name);
+}
+
+static gboolean
+impl_has_property (EphyEmbedEvent *event,
+ const char *name)
+{
+ gpointer tmp;
+
+ tmp = g_hash_table_lookup (((MozillaEmbedEvent *) event)->priv->props, name);
+
+ return tmp != NULL;
+}
+
+static gpointer
+impl_get_dom_event (EphyEmbedEvent *event)
+{
+ return static_cast<gpointer>(((MozillaEmbedEvent *) event)->priv->dom_event);
+}
+
+static void
+free_g_value (gpointer value)
+{
+ g_value_unset ((GValue *) value);
+ g_free (value);
+}
+
+static void
+mozilla_embed_event_init (MozillaEmbedEvent *event)
+{
+ event->priv = MOZILLA_EMBED_EVENT_GET_PRIVATE (event);
+
+ LOG ("MozillaEmbedEvent %p initialising", event);
+
+ event->priv->dom_event = nsnull;
+ event->priv->props = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, free_g_value);
+}
+
+static void
+mozilla_embed_event_finalize (GObject *object)
+{
+ MozillaEmbedEvent *event = MOZILLA_EMBED_EVENT (object);
+
+ g_hash_table_destroy (event->priv->props);
+
+ NS_IF_RELEASE (event->priv->dom_event);
+ event->priv->dom_event = nsnull;
+
+ LOG ("MozillaEmbedEvent %p finalised", object);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+ephy_embed_event_iface_init (EphyEmbedEventIface *iface)
+{
+ iface->get_context = impl_get_context;
+ iface->get_button = impl_get_button;
+ iface->get_modifier = impl_get_modifier;
+ iface->get_coordinates = impl_get_coordinates;
+ iface->get_property = impl_get_property;
+ iface->has_property = impl_has_property;
+ iface->get_dom_event = impl_get_dom_event;
+}
+
+static void
+mozilla_embed_event_class_init (MozillaEmbedEventClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
+
+ object_class->finalize = mozilla_embed_event_finalize;
+
+ g_type_class_add_private (object_class, sizeof (MozillaEmbedEventPrivate));
+}
diff --git a/embed/xulrunner/embed/mozilla-embed-event.h b/embed/xulrunner/embed/mozilla-embed-event.h
new file mode 100644
index 000000000..4306bef67
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-embed-event.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright © 2000-2003 Marco Pesenti Gritti
+ * Copyright © 2004 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef MOZILLA_EMBED_EVENT_H
+#define MOZILLA_EMBED_EVENT_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "ephy-embed-event.h"
+
+G_BEGIN_DECLS
+
+#define MOZILLA_TYPE_EMBED_EVENT (mozilla_embed_event_get_type ())
+#define MOZILLA_EMBED_EVENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MOZILLA_TYPE_EMBED_EVENT, MozillaEmbedEvent))
+#define MOZILLA_EMBED_EVENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MOZILLA_TYPE_EMBED_EVENT, MozillaEmbedEventClass))
+#define MOZILLA_IS_EMBED_EVENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MOZILLA_TYPE_EMBED_EVENT))
+#define MOZILLA_IS_EMBED_EVENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MOZILLA_TYPE_EMBED_EVENT))
+#define MOZILLA_EMBED_EVENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MOZILLA_TYPE_EMBED_EVENT, MozillaEmbedEventClass))
+
+typedef struct _MozillaEmbedEventClass MozillaEmbedEventClass;
+typedef struct _MozillaEmbedEvent MozillaEmbedEvent;
+typedef struct _MozillaEmbedEventPrivate MozillaEmbedEventPrivate;
+
+struct _MozillaEmbedEventClass
+{
+ GObjectClass parent_class;
+};
+
+struct _MozillaEmbedEvent
+{
+ GObject parent;
+
+ /*< private >*/
+ MozillaEmbedEventPrivate *priv;
+
+ /*< private >*/ /* public to the embed implementation */
+ guint button;
+ guint context;
+ guint modifier;
+ guint x;
+ guint y;
+ guint keycode;
+};
+
+GType mozilla_embed_event_get_type (void);
+
+MozillaEmbedEvent *mozilla_embed_event_new (gpointer dom_event);
+
+void mozilla_embed_event_set_property (MozillaEmbedEvent *event,
+ const char *name,
+ GValue *value);
+
+G_END_DECLS
+
+#endif
diff --git a/embed/xulrunner/embed/mozilla-embed-find.cpp b/embed/xulrunner/embed/mozilla-embed-find.cpp
new file mode 100644
index 000000000..576d8ec11
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-embed-find.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright © 2000-2004 Marco Pesenti Gritti
+ * Copyright © 2003, 2004 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include "ephy-debug.h"
+#include "ephy-embed-find.h"
+#include "ephy-embed-shell.h"
+
+#include "EphyFind.h"
+
+#include "mozilla-embed-find.h"
+
+#define MOZILLA_EMBED_FIND_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), MOZILLA_TYPE_EMBED_FIND, MozillaEmbedFindPrivate))
+
+struct _MozillaEmbedFindPrivate
+{
+ EphyFind *find;
+};
+
+static GObjectClass *parent_class = NULL;
+
+static void
+impl_set_embed (EphyEmbedFind *efind,
+ EphyEmbed *embed)
+{
+ MozillaEmbedFind *find = MOZILLA_EMBED_FIND (efind);
+ MozillaEmbedFindPrivate *priv = find->priv;
+
+ priv->find->SetEmbed (embed);
+}
+
+static void
+impl_set_properties (EphyEmbedFind *efind,
+ const char *find_string,
+ gboolean case_sensitive)
+{
+ MozillaEmbedFind *find = MOZILLA_EMBED_FIND (efind);
+ MozillaEmbedFindPrivate *priv = find->priv;
+
+ priv->find->SetFindProperties (find_string, case_sensitive);
+}
+
+static EphyEmbedFindResult
+impl_find (EphyEmbedFind *efind,
+ const char *find_string,
+ gboolean links_only)
+{
+ MozillaEmbedFind *find = MOZILLA_EMBED_FIND (efind);
+ MozillaEmbedFindPrivate *priv = find->priv;
+
+ return priv->find->Find (find_string, links_only);
+}
+
+static EphyEmbedFindResult
+impl_find_again (EphyEmbedFind *efind,
+ gboolean forward,
+ gboolean links_only)
+{
+ MozillaEmbedFind *find = MOZILLA_EMBED_FIND (efind);
+ MozillaEmbedFindPrivate *priv = find->priv;
+
+ return priv->find->FindAgain (forward, links_only);
+}
+
+static void
+impl_set_selection (EphyEmbedFind *efind,
+ gboolean attention)
+{
+ MozillaEmbedFind *find = MOZILLA_EMBED_FIND (efind);
+ MozillaEmbedFindPrivate *priv = find->priv;
+
+ priv->find->SetSelectionAttention (attention);
+}
+
+static gboolean
+impl_activate_link (EphyEmbedFind *efind,
+ GdkModifierType mask)
+{
+ MozillaEmbedFind *find = MOZILLA_EMBED_FIND (efind);
+ MozillaEmbedFindPrivate *priv = find->priv;
+
+ return priv->find->ActivateLink (mask);
+}
+
+static void
+ephy_find_iface_init (EphyEmbedFindIface *iface)
+{
+ iface->set_embed = impl_set_embed;
+ iface->set_properties = impl_set_properties;
+ iface->find = impl_find;
+ iface->find_again = impl_find_again;
+ iface->set_selection = impl_set_selection;
+ iface->activate_link = impl_activate_link;
+}
+
+static void
+mozilla_embed_find_init (MozillaEmbedFind *find)
+{
+ find->priv = MOZILLA_EMBED_FIND_GET_PRIVATE (find);
+ find->priv->find = new EphyFind ();
+}
+
+static GObject *
+mozilla_embed_find_constructor (GType type, guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ g_object_ref (embed_shell);
+
+ /* we depend on single because of mozilla initialization */
+ ephy_embed_shell_get_embed_single (embed_shell);
+
+ return parent_class->constructor (type, n_construct_properties,
+ construct_params);
+}
+
+static void
+mozilla_embed_find_finalize (GObject *object)
+{
+ MozillaEmbedFind *find = MOZILLA_EMBED_FIND (object);
+
+ delete find->priv->find;
+
+ parent_class->finalize (object);
+
+ g_object_unref (embed_shell);
+}
+
+static void
+mozilla_embed_find_class_init (MozillaEmbedFindClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
+
+ object_class->constructor = mozilla_embed_find_constructor;
+ object_class->finalize = mozilla_embed_find_finalize;
+
+ g_type_class_add_private (object_class, sizeof (MozillaEmbedFindPrivate));
+}
+
+GType
+mozilla_embed_find_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ const GTypeInfo our_info =
+ {
+ sizeof (MozillaEmbedFindClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) mozilla_embed_find_class_init,
+ NULL,
+ NULL, /* class_data */
+ sizeof (MozillaEmbedFind),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mozilla_embed_find_init
+ };
+
+ const GInterfaceInfo find_info =
+ {
+ (GInterfaceInitFunc) ephy_find_iface_init,
+ NULL,
+ NULL
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "MozillaEmbedFind",
+ &our_info,
+ (GTypeFlags)0);
+ g_type_add_interface_static (type,
+ EPHY_TYPE_EMBED_FIND,
+ &find_info);
+ }
+
+ return type;
+}
diff --git a/embed/xulrunner/embed/mozilla-embed-find.h b/embed/xulrunner/embed/mozilla-embed-find.h
new file mode 100644
index 000000000..1291f3795
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-embed-find.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2000-2004 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef MOZILLA_EMBED_FIND_H
+#define MOZILLA_EMBED_FIND_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MOZILLA_TYPE_EMBED_FIND (mozilla_embed_find_get_type ())
+#define MOZILLA_EMBED_FIND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MOZILLA_TYPE_EMBED_FIND, MozillaEmbedFind))
+#define MOZILLA_EMBED_FIND_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MOZILLA_TYPE_EMBED_FIND, MozillaEmbedFindClass))
+#define MOZILLA_IS_EMBED_FIND(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MOZILLA_TYPE_EMBED_FIND))
+#define MOZILLA_IS_EMBED_FIND_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MOZILLA_TYPE_EMBED_FIND))
+#define MOZILLA_EMBED_FIND_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MOZILLA_TYPE_EMBED_FIND, MozillaEmbedFindClass))
+
+typedef struct _MozillaEmbedFindClass MozillaEmbedFindClass;
+typedef struct _MozillaEmbedFind MozillaEmbedFind;
+typedef struct _MozillaEmbedFindPrivate MozillaEmbedFindPrivate;
+
+struct _MozillaEmbedFind
+{
+ GObject parent_instance;
+
+ /*< private >*/
+ MozillaEmbedFindPrivate *priv;
+};
+
+struct _MozillaEmbedFindClass
+{
+ GObjectClass parent_class;
+};
+
+GType mozilla_embed_find_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/embed/xulrunner/embed/mozilla-embed-persist.cpp b/embed/xulrunner/embed/mozilla-embed-persist.cpp
new file mode 100644
index 000000000..16909b49c
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-embed-persist.cpp
@@ -0,0 +1,416 @@
+/*
+ * Copyright © 2000, 2001, 2002 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <stddef.h>
+
+#include <nsStringAPI.h>
+
+#include <nsCOMPtr.h>
+#include <nsComponentManagerUtils.h>
+#include <nsCWebBrowserPersist.h>
+#include <nsICacheEntryDescriptor.h>
+#include <nsICacheService.h>
+#include <nsICacheSession.h>
+#include <nsIDOMSerializer.h>
+#include <nsIFile.h>
+#include <nsIHistoryEntry.h>
+#include <nsIInputStream.h>
+#include <nsIIOService.h>
+#include <nsILocalFile.h>
+#include <nsISHEntry.h>
+#include <nsIURI.h>
+#include <nsIWebBrowserPersist.h>
+#include <nsNetCID.h>
+#include <nsNetError.h>
+#include <nsServiceManagerUtils.h>
+#include <nsXPCOM.h>
+
+#include "EphyBrowser.h"
+#include "EphyHeaderSniffer.h"
+#include "EphyUtils.h"
+#include "MozDownload.h"
+
+#include "ephy-debug.h"
+#include "ephy-embed-shell.h"
+#include "ephy-file-helpers.h"
+#include "mozilla-embed.h"
+
+#include "mozilla-embed-persist.h"
+
+static void
+mozilla_embed_persist_class_init (MozillaEmbedPersistClass *klass);
+static void
+mozilla_embed_persist_init (MozillaEmbedPersist *ges);
+static void
+mozilla_embed_persist_finalize (GObject *object);
+
+#define MOZILLA_EMBED_PERSIST_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), MOZILLA_TYPE_EMBED_PERSIST, MozillaEmbedPersistPrivate))
+
+struct MozillaEmbedPersistPrivate
+{
+ nsCOMPtr<nsIWebBrowserPersist> mPersist;
+};
+
+static GObjectClass *parent_class = NULL;
+
+GType
+mozilla_embed_persist_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ const GTypeInfo our_info =
+ {
+ sizeof (MozillaEmbedPersistClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) mozilla_embed_persist_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (MozillaEmbedPersist),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mozilla_embed_persist_init
+ };
+
+ type = g_type_register_static (EPHY_TYPE_EMBED_PERSIST,
+ "MozillaEmbedPersist",
+ &our_info, (GTypeFlags) 0);
+ }
+
+ return type;
+}
+
+static void
+mozilla_embed_persist_init (MozillaEmbedPersist *persist)
+{
+ persist->priv = MOZILLA_EMBED_PERSIST_GET_PRIVATE (persist);
+
+ persist->priv->mPersist = do_CreateInstance (NS_WEBBROWSERPERSIST_CONTRACTID);
+}
+
+static void
+mozilla_embed_persist_finalize (GObject *object)
+{
+ MozillaEmbedPersist *persist = MOZILLA_EMBED_PERSIST (object);
+
+ persist->priv->mPersist = nsnull;
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+void
+mozilla_embed_persist_completed (MozillaEmbedPersist *persist)
+{
+ g_signal_emit_by_name (persist, "completed");
+ g_object_unref (persist);
+}
+
+void
+mozilla_embed_persist_cancelled (MozillaEmbedPersist *persist)
+{
+ g_signal_emit_by_name (persist, "cancelled");
+ g_object_unref (persist);
+}
+
+static void
+impl_cancel (EphyEmbedPersist *persist)
+{
+ nsCOMPtr<nsIWebBrowserPersist> bpersist =
+ MOZILLA_EMBED_PERSIST (persist)->priv->mPersist;
+ nsCOMPtr<nsICancelable> cancelable (do_QueryInterface (bpersist));
+ if (cancelable)
+ {
+ cancelable->Cancel (NS_BINDING_ABORTED);
+ }
+
+ g_object_unref (persist);
+}
+
+static gboolean
+impl_save (EphyEmbedPersist *persist)
+{
+ nsresult rv;
+ char *filename;
+ char *uri;
+ gint64 max_size;
+ EphyEmbed *embed;
+ EphyEmbedPersistFlags flags;
+ EphyEmbedSingle *single;
+
+ single = EPHY_EMBED_SINGLE (ephy_embed_shell_get_embed_single (embed_shell));
+
+ g_object_ref (persist);
+
+ g_object_get (persist,
+ "source", &uri,
+ "dest", &filename,
+ "flags", &flags,
+ "embed", &embed,
+ "max_size", &max_size,
+ (char *) NULL);
+
+ g_return_val_if_fail (!(flags & EPHY_EMBED_PERSIST_COPY_PAGE)
+ || embed != NULL, FALSE);
+
+ EphyBrowser *browser = NULL;
+ if (embed)
+ {
+ browser = (EphyBrowser *) _mozilla_embed_get_ephy_browser (MOZILLA_EMBED(embed));
+
+ g_object_unref (embed);
+
+ NS_ENSURE_TRUE (browser, FALSE);
+ }
+ /* we must have one of uri or browser */
+ g_assert (browser != NULL || uri != NULL);
+
+ /* Get the uri to save to */
+ nsCOMPtr<nsIURI> inURI;
+ if (uri)
+ {
+ /* FIXME: origin charset!! */
+ rv = EphyUtils::NewURI (getter_AddRefs(inURI), nsCString(uri));
+ NS_ENSURE_SUCCESS (rv, FALSE);
+ }
+ else
+ {
+ rv = browser->GetDocumentURI (getter_AddRefs (inURI));
+ NS_ENSURE_SUCCESS (rv, FALSE);
+ }
+
+ /* Get post data */
+ nsCOMPtr<nsIInputStream> postData;
+ /* FIXME: don't do this on COPY_PAGE to ensure we don't end up reposting? */
+ if (browser)
+ {
+ PRInt32 sindex;
+
+ nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(browser->mWebBrowser));
+ nsCOMPtr<nsISHistory> sessionHistory;
+ webNav->GetSessionHistory(getter_AddRefs(sessionHistory));
+ nsCOMPtr<nsIHistoryEntry> entry;
+ sessionHistory->GetIndex(&sindex);
+ sessionHistory->GetEntryAtIndex(sindex, PR_FALSE, getter_AddRefs(entry));
+ nsCOMPtr<nsISHEntry> shEntry(do_QueryInterface(entry));
+ if (shEntry)
+ {
+ shEntry->GetPostData(getter_AddRefs(postData));
+ }
+ }
+
+ /* Get the DOM document if a uri is not specified */
+ nsCOMPtr<nsIDOMDocument> DOMDocument;
+ if (!uri)
+ {
+ if (flags & EPHY_EMBED_PERSIST_MAINDOC)
+ {
+ browser->GetDocument (getter_AddRefs(DOMDocument));
+ }
+ else
+ {
+ browser->GetTargetDocument (getter_AddRefs(DOMDocument));
+ }
+ NS_ENSURE_TRUE (DOMDocument, FALSE);
+ }
+
+
+ /* Get the current page descriptor */
+ nsCOMPtr<nsISupports> cacheDescriptor;
+ if (browser)
+ {
+ browser->GetPageDescriptor(getter_AddRefs (cacheDescriptor));
+ }
+
+ /* Try to get a descriptor from the cache session */
+ /* FIXME: what about https?? */
+ PRBool isHttp = PR_FALSE, isHttps = PR_FALSE;
+ if (!cacheDescriptor &&
+ (flags & EPHY_EMBED_PERSIST_FROM_CACHE) &&
+ inURI &&
+ ((NS_SUCCEEDED (inURI->SchemeIs ("http", &isHttp)) && isHttp) ||
+ (NS_SUCCEEDED (inURI->SchemeIs ("https", &isHttps)) && isHttps )))
+ {
+ nsCOMPtr<nsICacheService> cacheService
+ (do_GetService(NS_CACHESERVICE_CONTRACTID));
+ if (cacheService)
+ {
+ nsCOMPtr<nsICacheSession> cacheSession;
+ rv = cacheService->CreateSession ("HTTP",
+ nsICache::STORE_ANYWHERE,
+ PR_TRUE,
+ getter_AddRefs (cacheSession));
+ if (NS_SUCCEEDED (rv) && cacheSession)
+ {
+ nsCOMPtr<nsICacheEntryDescriptor> descriptor;
+
+ nsCString spec;
+ inURI->GetSpec (spec);
+
+ rv = cacheSession->OpenCacheEntry
+ (spec,
+ nsICache::ACCESS_READ,
+ PR_FALSE, getter_AddRefs (descriptor));
+
+ cacheDescriptor = do_QueryInterface (descriptor);
+
+ LOG ("Getting cache descriptor for '%s' rv=%x", spec.get(), rv);
+ }
+ }
+ }
+
+ LOG ("Cache descriptor %p", cacheDescriptor.get());
+
+ /* if we have COPY_PAGE, we *need* to have a page descriptor, else we'll re-fetch
+ * the page, which will possibly give a different page than the original which we
+ * need for view source
+ */
+ NS_ENSURE_TRUE (!(flags & EPHY_EMBED_PERSIST_COPY_PAGE) || cacheDescriptor, FALSE);
+
+ if (filename == NULL || filename[0] == '\0')
+ {
+ /* Get a temp filename to save to */
+ char *tmp_filename, *base;
+ base = g_build_filename (g_get_tmp_dir (), "sav-XXXXXX", (char *) NULL);
+ tmp_filename = ephy_file_tmp_filename (base, "html");
+ g_free (base);
+ if (tmp_filename == NULL) return FALSE;
+
+ nsCOMPtr<nsILocalFile> tmpFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
+ NS_ENSURE_TRUE (tmpFile, FALSE);
+
+ tmpFile->InitWithNativePath (nsCString (tmp_filename));
+ g_free (tmp_filename);
+
+ /* Create an header sniffer and do the save */
+ nsCOMPtr<nsIWebBrowserPersist> webPersist =
+ MOZILLA_EMBED_PERSIST (persist)->priv->mPersist;
+ NS_ENSURE_TRUE (webPersist, FALSE);
+
+ EphyHeaderSniffer* sniffer = new EphyHeaderSniffer
+ (webPersist, MOZILLA_EMBED_PERSIST (persist),
+ tmpFile, inURI, DOMDocument, postData, single);
+ if (!sniffer) return FALSE;
+
+ webPersist->SetProgressListener(sniffer);
+ rv = webPersist->SaveURI(inURI, cacheDescriptor, nsnull /* FIXME: Referrer */, nsnull, nsnull, tmpFile);
+ if (NS_FAILED (rv)) return FALSE;
+ }
+ else
+ {
+ /* Filename to save to */
+ nsCOMPtr<nsILocalFile> destFile;
+ NS_NewNativeLocalFile (nsCString(filename),
+ PR_TRUE, getter_AddRefs(destFile));
+ NS_ENSURE_TRUE (destFile, FALSE);
+
+ rv = InitiateMozillaDownload (DOMDocument, inURI, destFile,
+ nsnull, inURI, MOZILLA_EMBED_PERSIST (persist),
+ postData, cacheDescriptor, max_size);
+ if (NS_FAILED (rv)) return FALSE;
+ }
+
+ g_free (uri);
+ g_free (filename);
+
+ return TRUE;
+}
+
+static char *
+impl_to_string (EphyEmbedPersist *persist)
+{
+ EphyEmbed *embed;
+ nsCOMPtr<nsIDOMDocument> DOMDocument;
+ EphyEmbedPersistFlags flags;
+ EphyBrowser *browser;
+ nsresult rv = NS_OK;
+
+ g_object_ref (persist);
+
+ g_object_get (persist,
+ "flags", &flags,
+ "embed", &embed,
+ (char *) NULL);
+ g_object_unref (persist);
+ g_return_val_if_fail (embed != NULL, NULL);
+
+ browser = (EphyBrowser *) _mozilla_embed_get_ephy_browser (MOZILLA_EMBED(embed));
+ g_return_val_if_fail (browser != NULL, NULL);
+
+ if (flags & EPHY_EMBED_PERSIST_MAINDOC)
+ {
+ rv = browser->GetDocument (getter_AddRefs(DOMDocument));
+ }
+ else
+ {
+ rv = browser->GetTargetDocument (getter_AddRefs(DOMDocument));
+ }
+
+ nsCString cOutString;
+ nsCOMPtr<nsIDOMNode> node = do_QueryInterface(DOMDocument);
+ if (node)
+ {
+ nsString outString;
+ nsCOMPtr<nsIDOMSerializer> serializer;
+ serializer = do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv);
+ if (serializer)
+ {
+ serializer->SerializeToString(node, outString);
+
+ NS_UTF16ToCString (outString, NS_CSTRING_ENCODING_UTF8, cOutString);
+ }
+ }
+
+ g_object_unref (embed);
+
+ return g_strdup (cOutString.get());
+}
+
+static GObject *
+mozilla_embed_persist_constructor (GType type, guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ /* this will ensure that mozilla is started up */
+ ephy_embed_shell_get_embed_single (embed_shell);
+
+ return parent_class->constructor (type, n_construct_properties,
+ construct_params);
+}
+
+static void
+mozilla_embed_persist_class_init (MozillaEmbedPersistClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ EphyEmbedPersistClass *persist_class = EPHY_EMBED_PERSIST_CLASS (klass);
+
+ parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
+
+ object_class->finalize = mozilla_embed_persist_finalize;
+ object_class->constructor = mozilla_embed_persist_constructor;
+
+ persist_class->save = impl_save;
+ persist_class->cancel = impl_cancel;
+ persist_class->to_string = impl_to_string;
+
+ g_type_class_add_private (object_class, sizeof(MozillaEmbedPersistPrivate));
+}
diff --git a/embed/xulrunner/embed/mozilla-embed-persist.h b/embed/xulrunner/embed/mozilla-embed-persist.h
new file mode 100644
index 000000000..edcb1eb53
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-embed-persist.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2000-2003 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef MOZILLA_EMBED_PERSIST_H
+#define MOZILLA_EMBED_PERSIST_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "ephy-embed-persist.h"
+
+G_BEGIN_DECLS
+
+#define MOZILLA_TYPE_EMBED_PERSIST (mozilla_embed_persist_get_type ())
+#define MOZILLA_EMBED_PERSIST(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MOZILLA_TYPE_EMBED_PERSIST, MozillaEmbedPersist))
+#define MOZILLA_EMBED_PERSIST_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MOZILLA_TYPE_EMBED_PERSIST, MozillaEmbedPersistClass))
+#define MOZILLA_IS_EMBED_PERSIST(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MOZILLA_TYPE_EMBED_PERSIST))
+#define MOZILLA_IS_EMBED_PERSIST_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MOZILLA_TYPE_EMBED_PERSIST))
+#define MOZILLA_EMBED_PERSIST_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MOZILLA_TYPE_EMBED_PERSIST, MozillaEmbedPersistClass))
+
+typedef struct MozillaEmbedPersistClass MozillaEmbedPersistClass;
+typedef struct MozillaEmbedPersist MozillaEmbedPersist;
+typedef struct MozillaEmbedPersistPrivate MozillaEmbedPersistPrivate;
+
+struct MozillaEmbedPersist
+{
+ EphyEmbedPersist parent;
+
+ /*< private >*/
+ MozillaEmbedPersistPrivate *priv;
+};
+
+struct MozillaEmbedPersistClass
+{
+ EphyEmbedPersistClass parent_class;
+};
+
+GType mozilla_embed_persist_get_type (void);
+
+void mozilla_embed_persist_completed (MozillaEmbedPersist *persist);
+
+void mozilla_embed_persist_cancelled (MozillaEmbedPersist *persist);
+
+G_END_DECLS
+
+#endif
diff --git a/embed/xulrunner/embed/mozilla-embed-single.cpp b/embed/xulrunner/embed/mozilla-embed-single.cpp
new file mode 100644
index 000000000..1ebc2252c
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-embed-single.cpp
@@ -0,0 +1,1445 @@
+/* vim:set ts=8 noet sw=8:
+ * Copyright © 2000-2004 Marco Pesenti Gritti
+ * Copyright © 2003 Robert Marcano
+ * Copyright © 2003, 2004, 2005, 2006 Christian Persch
+ * Copyright © 2005 Crispin Flowerday
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+
+#include <nsStringAPI.h>
+
+#include <nsComponentManagerUtils.h>
+#include <nsCOMPtr.h>
+#include <nsCPasswordManager.h>
+#include <nsICookie2.h>
+#include <nsICookieManager.h>
+#include <nsICookieManager.h>
+#include <nsIFile.h>
+#include <nsIIOService.h>
+#include <nsILocalFile.h>
+#include <nsIPermission.h>
+#include <nsIPermissionManager.h>
+#include <nsIPrefService.h>
+#include <nsIStyleSheetService.h>
+#include <nsISupportsPrimitives.h>
+#include <nsIURI.h>
+#include <nsIWindowWatcher.h>
+#include <nsMemory.h>
+#include <nsServiceManagerUtils.h>
+
+#ifdef HAVE_MOZILLA_PSM
+#include <nsIX509Cert.h>
+#include <nsIX509CertDB.h>
+#endif
+
+#ifdef ALLOW_PRIVATE_API
+#include <nsICacheService.h>
+#include <nsIFontEnumerator.h>
+#include <nsIHttpAuthManager.h>
+#include <nsIIDNService.h>
+#include <nsNetCID.h>
+#endif /* ALLOW_PRIVATE_API */
+
+#ifndef HAVE_GECKO_1_9
+#include <nsIPassword.h>
+#include <nsIPasswordManager.h>
+#endif /* !HAVE_GECKO_1_9 */
+
+#define XPCOM_GLUE
+#include <nsXPCOMGlue.h>
+
+#include "gecko-init.h"
+#include "gecko-init-internal.h"
+#include "gecko-embed.h"
+#include "gecko-embed-single.h"
+
+#include "ephy-file-helpers.h"
+#include "eel-gconf-extensions.h"
+#include "ephy-certificate-manager.h"
+#include "ephy-cookie-manager.h"
+#include "ephy-debug.h"
+#include "ephy-embed-prefs.h"
+#include "ephy-embed-shell.h"
+#include "ephy-file-helpers.h"
+#include "ephy-langs.h"
+#include "ephy-password-manager.h"
+#include "ephy-permission-manager.h"
+#include "mozilla-embed.h"
+#include "mozilla-notifiers.h"
+#include "mozilla-x509-cert.h"
+
+#include "EphyBrowser.h"
+#include "EphyDirectoryProvider.h"
+#include "EphySingle.h"
+#include "EphyUtils.h"
+#include "MozRegisterComponents.h"
+
+#include "mozilla-embed-single.h"
+
+#include "AutoJSContextStack.h"
+
+#define MOZILLA_PROFILE_DIR "/mozilla"
+#define MOZILLA_PROFILE_NAME "epiphany"
+#define MOZILLA_PROFILE_FILE "prefs.js"
+#define DEFAULT_PROFILE_FILE SHARE_DIR"/default-prefs.js"
+
+#define USER_CSS_LOAD_DELAY 500 /* ms */
+
+#define MOZILLA_EMBED_SINGLE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), MOZILLA_TYPE_EMBED_SINGLE, MozillaEmbedSinglePrivate))
+
+struct MozillaEmbedSinglePrivate
+{
+ char *user_prefs;
+
+ EphySingle *mSingleObserver;
+
+ char *user_css_file;
+ guint user_css_enabled_notifier_id;
+ EphyFileMonitor *user_css_file_monitor;
+ guint user_css_enabled : 1;
+
+ guint online : 1;
+};
+
+enum
+{
+ PROP_0,
+ PROP_NETWORK_STATUS
+};
+
+static void mozilla_embed_single_class_init (MozillaEmbedSingleClass *klass);
+static void ephy_embed_single_iface_init (EphyEmbedSingleIface *iface);
+static void ephy_cookie_manager_iface_init (EphyCookieManagerIface *iface);
+static void ephy_password_manager_iface_init (EphyPasswordManagerIface *iface);
+static void ephy_permission_manager_iface_init (EphyPermissionManagerIface *iface);
+static void mozilla_embed_single_init (MozillaEmbedSingle *ges);
+
+#ifdef ENABLE_CERTIFICATE_MANAGER
+static void ephy_certificate_manager_iface_init (EphyCertificateManagerIface *iface);
+#endif
+
+static GObjectClass *parent_class = NULL;
+
+GType
+mozilla_embed_single_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ const GTypeInfo our_info =
+ {
+ sizeof (MozillaEmbedSingleClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) mozilla_embed_single_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (MozillaEmbedSingle),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mozilla_embed_single_init
+ };
+
+ const GInterfaceInfo embed_single_info =
+ {
+ (GInterfaceInitFunc) ephy_embed_single_iface_init,
+ NULL,
+ NULL
+ };
+
+ const GInterfaceInfo cookie_manager_info =
+ {
+ (GInterfaceInitFunc) ephy_cookie_manager_iface_init,
+ NULL,
+ NULL
+ };
+
+ const GInterfaceInfo password_manager_info =
+ {
+ (GInterfaceInitFunc) ephy_password_manager_iface_init,
+ NULL,
+ NULL
+ };
+
+ const GInterfaceInfo permission_manager_info =
+ {
+ (GInterfaceInitFunc) ephy_permission_manager_iface_init,
+ NULL,
+ NULL
+ };
+
+#ifdef ENABLE_CERTIFICATE_MANAGER
+ const GInterfaceInfo certificate_manager_info =
+ {
+ (GInterfaceInitFunc) ephy_certificate_manager_iface_init,
+ NULL,
+ NULL
+ };
+#endif
+
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "MozillaEmbedSingle",
+ &our_info,
+ (GTypeFlags)0);
+
+ g_type_add_interface_static (type,
+ EPHY_TYPE_EMBED_SINGLE,
+ &embed_single_info);
+
+ g_type_add_interface_static (type,
+ EPHY_TYPE_COOKIE_MANAGER,
+ &cookie_manager_info);
+
+ g_type_add_interface_static (type,
+ EPHY_TYPE_PASSWORD_MANAGER,
+ &password_manager_info);
+
+ g_type_add_interface_static (type,
+ EPHY_TYPE_PERMISSION_MANAGER,
+ &permission_manager_info);
+#ifdef ENABLE_CERTIFICATE_MANAGER
+ g_type_add_interface_static (type,
+ EPHY_TYPE_CERTIFICATE_MANAGER,
+ &certificate_manager_info);
+#endif
+ }
+
+ return type;
+}
+
+static gboolean
+mozilla_set_default_prefs (MozillaEmbedSingle *mes)
+{
+ nsCOMPtr<nsIPrefService> prefService;
+
+ prefService = do_GetService (NS_PREFSERVICE_CONTRACTID);
+ NS_ENSURE_TRUE (prefService, FALSE);
+
+ /* read our predefined default prefs */
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file;
+ NS_NewNativeLocalFile(nsCString(DEFAULT_PROFILE_FILE),
+ PR_TRUE, getter_AddRefs(file));
+ if (!file) return FALSE;
+
+ rv = prefService->ReadUserPrefs (file);
+ if (NS_FAILED(rv))
+ {
+ g_warning ("failed to read default preferences, error: %x", rv);
+ return FALSE;
+ }
+
+ nsCOMPtr<nsIPrefBranch> pref;
+ prefService->GetBranch ("", getter_AddRefs(pref));
+ NS_ENSURE_TRUE (pref, FALSE);
+
+ /* We do this before reading the user pref file so that the user
+ * still can overwrite this pref.
+ * We don't use the default-prefs.js file since that cannot be
+ * localised (see bug #144909).
+ */
+ /* translators: this is the URL that searches from the location
+ * entry get directed to. The search terms will be _appended_ to it,
+ * in url-escaped UTF-8; that means that if you're choosing google,
+ * the 'q=' part needs to come last.
+ */
+ pref->SetCharPref ("keyword.URL", _("http://www.google.com/search?ie=UTF-8&oe=UTF-8&q="));
+
+ /* Load the default user preferences as well. This also makes the
+ prefs to be saved in the user's prefs.js file, instead of messing up
+ our global defaults file. */
+ rv = prefService->ReadUserPrefs (nsnull);
+ if (NS_FAILED(rv))
+ {
+ g_warning ("failed to read user preferences, error: %x", rv);
+ }
+
+ pref->SetCharPref ("general.useragent.extra.epiphany", "Epiphany/" UA_VERSION);
+
+ /* Unset old prefs, otherwise they end up in the user agent string too */
+ pref->ClearUserPref ("general.useragent.vendor");
+ pref->ClearUserPref ("general.useragent.vendorSub");
+
+ /* Don't open ftp uris with an external handler if one is setup */
+ pref->SetBoolPref ("network.protocol-handler.external.ftp", PR_FALSE);
+
+ return TRUE;
+}
+
+static void
+mozilla_embed_single_new_window_orphan_cb (GeckoEmbedSingle *moz_single,
+ GeckoEmbed **newEmbed,
+ guint chrome_mask,
+ EphyEmbedSingle *single)
+{
+ GeckoEmbedChromeFlags chrome = (GeckoEmbedChromeFlags) chrome_mask;
+ EphyEmbed *new_embed = NULL;
+ EphyEmbedChrome mask;
+
+ if (chrome_mask & GECKO_EMBED_FLAG_OPENASCHROME)
+ {
+ *newEmbed = _mozilla_embed_new_xul_dialog ();
+ return;
+ }
+
+ mask = _mozilla_embed_translate_chrome (chrome);
+
+ g_signal_emit_by_name (single, "new-window", NULL, mask,
+ &new_embed);
+
+ /* it's okay not to have a new embed */
+ if (new_embed != NULL)
+ {
+ gecko_embed_set_chrome_mask (GECKO_EMBED (new_embed), chrome);
+
+ *newEmbed = GECKO_EMBED (new_embed);
+ }
+}
+
+static GList *
+mozilla_init_plugin_add_unique_path (GList *list,
+ const char *path)
+{
+ GList *l;
+ char *canon;
+
+ if (path == NULL)
+ return list;
+
+ canon = gnome_vfs_make_path_name_canonical (path);
+ for (l = list; l != NULL; l = l->next) {
+ if (g_str_equal (list->data, canon) != FALSE) {
+ /* The path is already in the list */
+ g_free (canon);
+ return list;
+ }
+ }
+ return g_list_prepend (list, canon);
+}
+
+static GList *
+mozilla_init_plugin_add_unique_paths (GList *list,
+ const char *path)
+{
+ char **paths;
+ guint i;
+
+ if (path == NULL)
+ return list;
+
+ paths = g_strsplit (path, ":", -1);
+ if (paths == NULL)
+ return list;
+ for (i = 0; paths[i] != NULL; i++) {
+ list = mozilla_init_plugin_add_unique_path (list, paths[i]);
+ }
+ g_strfreev (paths);
+ return list;
+}
+
+static void
+mozilla_init_plugin_path ()
+{
+ GList *list, *l;
+ GString *path;
+
+ list = NULL;
+ list = mozilla_init_plugin_add_unique_paths (list,
+ g_getenv ("MOZ_PLUGIN_PATH"));
+ list = mozilla_init_plugin_add_unique_path (list,
+ MOZILLA_PREFIX "/lib/mozilla/plugins");
+ list = mozilla_init_plugin_add_unique_path (list,
+ MOZILLA_HOME "/plugins");
+ list = mozilla_init_plugin_add_unique_path (list,
+ MOZILLA_NATIVE_PLUGINSDIR);
+#ifdef HAVE_PRIVATE_PLUGINS
+ list = mozilla_init_plugin_add_unique_path (list, PLUGINDIR);
+#endif
+
+ list = g_list_reverse (list);
+ path = g_string_new ((const char *) list->data);
+ g_free (list->data);
+ l = list->next;
+ for (; l != NULL; l = l->next) {
+ path = g_string_append_c (path, ':');
+ path = g_string_append (path, (const char *) l->data);
+ g_free (l->data);
+ }
+ g_list_free (list);
+
+ g_setenv ("MOZ_PLUGIN_PATH", path->str, TRUE);
+ g_string_free (path, TRUE);
+}
+
+static void
+mozilla_init_single (MozillaEmbedSingle *mes)
+{
+ GeckoEmbedSingle *single;
+
+ /* get single */
+ single = gecko_embed_single_get ();
+ if (single == NULL)
+ {
+ g_warning ("Failed to get singleton embed object!\n");
+ return;
+ }
+
+ /* allow creation of orphan windows */
+ g_signal_connect (G_OBJECT (single), "new_window_orphan",
+ G_CALLBACK (mozilla_embed_single_new_window_orphan_cb),
+ mes);
+}
+
+#if defined(MOZ_NSIXULCHROMEREGISTRY_SELECTSKIN) || defined(HAVE_CHROME_NSICHROMEREGISTRYSEA_H)
+static nsresult
+getUILang (nsAString& aUILang)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsILocaleService> localeService = do_GetService (NS_LOCALESERVICE_CONTRACTID);
+ if (!localeService)
+ {
+ g_warning ("Could not get locale service!\n");
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = localeService->GetLocaleComponentForUserAgent (aUILang);
+
+ if (NS_FAILED (rv))
+ {
+ g_warning ("Could not determine locale!\n");
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+#endif
+
+static void
+mozilla_init_observer (MozillaEmbedSingle *single)
+{
+ EphySingle *es;
+
+ es = new EphySingle ();
+ NS_ADDREF (single->priv->mSingleObserver = es);
+
+ nsresult rv;
+ rv = es->Init (EPHY_EMBED_SINGLE (single));
+ if (NS_FAILED (rv))
+ {
+ g_warning ("Failed to initialise EphySingle!\n");
+ return;
+ }
+}
+
+static void
+user_css_register (MozillaEmbedSingle *single)
+{
+ MozillaEmbedSinglePrivate *priv = single->priv;
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file;
+ rv = NS_NewNativeLocalFile (nsDependentCString (priv->user_css_file),
+ PR_TRUE, getter_AddRefs (file));
+ NS_ENSURE_SUCCESS (rv, );
+
+ PRBool exists = PR_FALSE;
+ rv = file->Exists (&exists);
+ if (NS_FAILED (rv) || !exists) return;
+
+ nsCOMPtr<nsIURI> uri;
+ rv = EphyUtils::NewFileURI (getter_AddRefs (uri), file);
+ NS_ENSURE_SUCCESS (rv, );
+
+ nsCOMPtr<nsIStyleSheetService> service
+ (do_GetService ("@mozilla.org/content/style-sheet-service;1", &rv));
+ NS_ENSURE_SUCCESS (rv, );
+
+ PRBool isRegistered = PR_FALSE;
+ rv = service->SheetRegistered (uri, nsIStyleSheetService::USER_SHEET,
+ &isRegistered);
+ if (NS_SUCCEEDED (rv) && isRegistered)
+ {
+ rv = service->UnregisterSheet (uri, nsIStyleSheetService::USER_SHEET);
+ }
+
+ rv = service->LoadAndRegisterSheet (uri, nsIStyleSheetService::AGENT_SHEET);
+ if (NS_FAILED (rv))
+ {
+ g_warning ("Registering the user stylesheet failed (rv=%x)!\n", rv);
+ }
+}
+
+static void
+user_css_unregister (MozillaEmbedSingle *single)
+{
+ MozillaEmbedSinglePrivate *priv = single->priv;
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file;
+ rv = NS_NewNativeLocalFile (nsDependentCString (priv->user_css_file),
+ PR_TRUE, getter_AddRefs (file));
+ NS_ENSURE_SUCCESS (rv, );
+
+ nsCOMPtr<nsIURI> uri;
+ rv = EphyUtils::NewFileURI (getter_AddRefs (uri), file);
+ NS_ENSURE_SUCCESS (rv, );
+
+ nsCOMPtr<nsIStyleSheetService> service
+ (do_GetService ("@mozilla.org/content/style-sheet-service;1", &rv));
+ NS_ENSURE_SUCCESS (rv, );
+
+ PRBool isRegistered = PR_FALSE;
+ rv = service->SheetRegistered (uri, nsIStyleSheetService::USER_SHEET,
+ &isRegistered);
+ if (NS_SUCCEEDED (rv) && isRegistered)
+ {
+ rv = service->UnregisterSheet (uri, nsIStyleSheetService::USER_SHEET);
+ }
+ if (NS_FAILED (rv))
+ {
+ g_warning ("Unregistering the user stylesheet failed (rv=%x)!\n", rv);
+ }
+}
+
+static void
+user_css_file_monitor_func (EphyFileMonitor *,
+ const char *,
+ GnomeVFSMonitorEventType event_type,
+ MozillaEmbedSingle *single)
+{
+ LOG ("Reregistering the user style sheet");
+
+ if (event_type == GNOME_VFS_MONITOR_EVENT_DELETED)
+ {
+ user_css_unregister (single);
+ }
+ else
+ {
+ user_css_register (single);
+ }
+}
+
+static void
+user_css_enabled_notify (GConfClient *client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ MozillaEmbedSingle *single)
+{
+ MozillaEmbedSinglePrivate *priv = single->priv;
+ guint enabled;
+
+ enabled = eel_gconf_get_boolean (CONF_USER_CSS_ENABLED) != FALSE;
+ if (priv->user_css_enabled == enabled) return;
+
+ LOG ("User stylesheet enabled: %s", enabled ? "t" : "f");
+
+ priv->user_css_enabled = enabled;
+
+ if (enabled)
+ {
+ char *uri;
+
+ user_css_register (single);
+
+ uri = gnome_vfs_get_uri_from_local_path (priv->user_css_file);
+
+ g_assert (priv->user_css_file_monitor == NULL);
+ priv->user_css_file_monitor =
+ ephy_file_monitor_add (uri,
+ GNOME_VFS_MONITOR_FILE,
+ USER_CSS_LOAD_DELAY,
+ (EphyFileMonitorFunc) user_css_file_monitor_func,
+ NULL,
+ single);
+ g_free (uri);
+ }
+ else
+ {
+ if (priv->user_css_file_monitor != NULL)
+ {
+ ephy_file_monitor_cancel (priv->user_css_file_monitor);
+ priv->user_css_file_monitor = NULL;
+ }
+
+ user_css_unregister (single);
+ }
+}
+
+static void
+mozilla_stylesheet_init (MozillaEmbedSingle *single)
+{
+ MozillaEmbedSinglePrivate *priv = single->priv;
+
+ priv->user_css_file = g_build_filename (ephy_dot_dir (),
+ USER_STYLESHEET_FILENAME,
+ (char *) NULL);
+
+ user_css_enabled_notify (NULL, 0, NULL, single);
+ priv->user_css_enabled_notifier_id =
+ eel_gconf_notification_add
+ (CONF_USER_CSS_ENABLED,
+ (GConfClientNotifyFunc) user_css_enabled_notify,
+ single);
+}
+
+static void
+mozilla_stylesheet_shutdown (MozillaEmbedSingle *single)
+{
+ MozillaEmbedSinglePrivate *priv = single->priv;
+
+ if (priv->user_css_enabled_notifier_id != 0)
+ {
+ eel_gconf_notification_remove (priv->user_css_enabled_notifier_id);
+ priv->user_css_enabled_notifier_id = 0;
+ }
+
+ if (priv->user_css_file_monitor != NULL)
+ {
+ ephy_file_monitor_cancel (priv->user_css_file_monitor);
+ priv->user_css_file_monitor = NULL;
+ }
+
+ if (priv->user_css_file != NULL)
+ {
+ g_free (priv->user_css_file);
+ priv->user_css_file = NULL;
+ }
+}
+
+static gboolean
+impl_init (EphyEmbedSingle *esingle)
+{
+ MozillaEmbedSingle *single = MOZILLA_EMBED_SINGLE (esingle);
+ char *profile_path;
+
+ g_setenv ("MOZILLA_POSTSCRIPT_ENABLED", "1", TRUE);
+ g_unsetenv ("MOZILLA_POSTSCRIPT_PRINTER_LIST");
+
+ NS_LogInit ();
+
+ /* Pre initialization */
+ mozilla_init_plugin_path ();
+
+ profile_path = g_build_filename (ephy_dot_dir (),
+ MOZILLA_PROFILE_DIR,
+ (char *) NULL);
+
+// gecko_embed_set_comp_path (MOZILLA_HOME);
+
+ static const GREVersionRange greVersion = {
+ "1.9a", PR_TRUE,
+ "2", PR_TRUE
+ };
+
+ char xpcomPath[PATH_MAX];
+
+ nsresult rv = GRE_GetGREPathWithProperties(&greVersion, 1, nsnull, 0,
+ xpcomPath, sizeof(xpcomPath));
+ if (NS_FAILED(rv)) {
+ fprintf(stderr, "Couldn't find a compatible GRE.\n");
+ return 1;
+ }
+
+ rv = XPCOMGlueStartup(xpcomPath);
+ if (NS_FAILED(rv)) {
+ fprintf(stderr, "Couldn't start XPCOM.");
+ return 1;
+ }
+
+ char *lastSlash = strrchr(xpcomPath, '/');
+ if (lastSlash)
+ *lastSlash = '\0';
+
+
+ nsCOMPtr<nsIDirectoryServiceProvider> dp = new EphyDirectoryProvider ();
+ if (!dp) return FALSE;
+
+ if (!gecko_init_with_params (xpcomPath,
+ profile_path,
+ MOZILLA_PROFILE_NAME,
+ dp)) {
+ g_free (profile_path);
+ g_warning ("Failed to init gecko!\n");
+ return FALSE;
+ }
+
+ g_free (profile_path);
+
+ mozilla_register_components ();
+
+ mozilla_init_single (single);
+
+ if (!mozilla_set_default_prefs (single))
+ {
+ return FALSE;
+ }
+
+ START_PROFILER ("Mozilla prefs notifiers")
+ mozilla_notifiers_init ();
+ STOP_PROFILER ("Mozilla prefs notifiers")
+
+ mozilla_init_observer (single);
+
+ mozilla_stylesheet_init (single);
+
+ return TRUE;
+}
+
+static void
+prepare_close_cb (EphyEmbedShell *shell)
+{
+ GValue value = { 0, };
+
+ /* To avoid evil web sites posing an alert and thus inhibiting
+ * shutdown, we just turn off javascript! :)
+ */
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&value, FALSE);
+ mozilla_pref_set ("javascript.enabled", &value);
+ g_value_unset (&value);
+}
+
+static void
+mozilla_embed_single_init (MozillaEmbedSingle *mes)
+{
+ mes->priv = MOZILLA_EMBED_SINGLE_GET_PRIVATE (mes);
+
+ mes->priv->user_prefs =
+ g_build_filename (ephy_dot_dir (),
+ MOZILLA_PROFILE_DIR,
+ MOZILLA_PROFILE_NAME,
+ MOZILLA_PROFILE_FILE,
+ (char *) NULL);
+
+ g_signal_connect_object (embed_shell, "prepare-close",
+ G_CALLBACK (prepare_close_cb), mes,
+ (GConnectFlags) 0);
+}
+
+static void
+mozilla_embed_single_dispose (GObject *object)
+{
+ MozillaEmbedSingle *single = MOZILLA_EMBED_SINGLE (object);
+ MozillaEmbedSinglePrivate *priv = single->priv;
+
+ mozilla_stylesheet_shutdown (single);
+
+ if (priv->mSingleObserver)
+ {
+ priv->mSingleObserver->Detach ();
+ NS_RELEASE (priv->mSingleObserver);
+ priv->mSingleObserver = nsnull;
+ }
+
+ parent_class->dispose (object);
+}
+
+static void
+mozilla_embed_single_finalize (GObject *object)
+{
+ MozillaEmbedSingle *mes = MOZILLA_EMBED_SINGLE (object);
+
+ /* Destroy EphyEmbedSingle before because some
+ * services depend on xpcom */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+
+ mozilla_notifiers_shutdown ();
+
+ gecko_shutdown ();
+
+ XPCOMGlueShutdown ();
+
+ NS_LogTerm ();
+
+ g_free (mes->priv->user_prefs);
+}
+
+static void
+impl_clear_cache (EphyEmbedSingle *shell)
+{
+ nsCOMPtr<nsICacheService> cacheService =
+ do_GetService (NS_CACHESERVICE_CONTRACTID);
+ if (!cacheService) return;
+
+ cacheService->EvictEntries (nsICache::STORE_ANYWHERE);
+}
+
+static void
+impl_clear_auth_cache (EphyEmbedSingle *shell)
+{
+ nsCOMPtr<nsIHttpAuthManager> authManager =
+ do_GetService (NS_HTTPAUTHMANAGER_CONTRACTID);
+ if (!authManager) return;
+
+ authManager->ClearAll();
+}
+
+static void
+impl_set_network_status (EphyEmbedSingle *single,
+ gboolean online)
+{
+ nsCOMPtr<nsIIOService> io = do_GetService(NS_IOSERVICE_CONTRACTID);
+ if (!io) return;
+
+ io->SetOffline (!online);
+}
+
+static gboolean
+impl_get_network_status (EphyEmbedSingle *esingle)
+{
+ MozillaEmbedSingle *single = MOZILLA_EMBED_SINGLE (esingle);
+ MozillaEmbedSinglePrivate *priv = single->priv;
+
+ NS_ENSURE_TRUE (priv->mSingleObserver, TRUE);
+
+ nsCOMPtr<nsIIOService> io = do_GetService(NS_IOSERVICE_CONTRACTID);
+ if (!io) return FALSE; /* no way to check the state, assume offline */
+
+ PRBool isOffline;
+ nsresult rv;
+ rv = io->GetOffline(&isOffline);
+ NS_ENSURE_SUCCESS (rv, FALSE);
+
+ PRBool isOnline = !isOffline;
+ PRBool reallyOnline = priv->mSingleObserver->IsOnline ();
+
+ g_return_val_if_fail (reallyOnline == isOnline, TRUE);
+
+ return !isOffline;
+}
+
+static const char*
+impl_get_backend_name (EphyEmbedSingle *esingle)
+{
+ /* If you alter the return values here, remember to update
+ * the docs in ephy-embed-single.c */
+#if defined (HAVE_GECKO_1_10)
+# error "Need to add version string for gecko 1.10"
+#elif defined(HAVE_GECKO_1_9)
+ return "gecko-1.9";
+#elif defined(HAVE_GECKO_1_8)
+ return "gecko-1.8";
+#else
+# error "Undefined/unsupported gecko version!"
+#endif
+}
+
+static GList *
+impl_get_font_list (EphyEmbedSingle *shell,
+ const char *langGroup)
+{
+ nsresult rv;
+ PRUint32 fontCount;
+ PRUnichar **fontArray;
+ GList *l = NULL;
+
+ nsCOMPtr<nsIFontEnumerator> mozFontEnumerator;
+ mozFontEnumerator = do_CreateInstance("@mozilla.org/gfx/fontenumerator;1");
+ NS_ENSURE_TRUE (mozFontEnumerator, NULL);
+
+ rv = mozFontEnumerator->EnumerateFonts (langGroup, nsnull,
+ &fontCount, &fontArray);
+ NS_ENSURE_SUCCESS (rv, NULL);
+
+ for (PRUint32 i = 0; i < fontCount; i++)
+ {
+ char *gFontString;
+
+ nsCString tmp;
+ NS_UTF16ToCString (nsString(fontArray[i]),
+ NS_CSTRING_ENCODING_UTF8, tmp);
+ gFontString = g_strdup (tmp.get());
+ l = g_list_prepend (l, gFontString);
+ nsMemory::Free (fontArray[i]);
+ }
+
+ nsMemory::Free (fontArray);
+
+ return g_list_reverse (l);
+}
+
+static GList *
+impl_list_cookies (EphyCookieManager *manager)
+{
+ nsresult rv;
+ GList *cookies = NULL;
+
+ nsCOMPtr<nsICookieManager> cookieManager =
+ do_GetService (NS_COOKIEMANAGER_CONTRACTID);
+ if (!cookieManager) return NULL;
+
+ nsCOMPtr<nsISimpleEnumerator> cookieEnumerator;
+ cookieManager->GetEnumerator (getter_AddRefs(cookieEnumerator));
+ NS_ENSURE_TRUE (cookieEnumerator, NULL);
+
+ PRBool enumResult;
+ for (cookieEnumerator->HasMoreElements(&enumResult) ;
+ enumResult == PR_TRUE ;
+ cookieEnumerator->HasMoreElements(&enumResult))
+ {
+ nsCOMPtr<nsICookie> keks;
+ rv = cookieEnumerator->GetNext (getter_AddRefs(keks));
+ if (NS_FAILED (rv) || !keks) continue;
+
+ EphyCookie *cookie = mozilla_cookie_to_ephy_cookie (keks);
+ if (!cookie) continue;
+
+ cookies = g_list_prepend (cookies, cookie);
+ }
+
+ return cookies;
+}
+
+static void
+impl_remove_cookie (EphyCookieManager *manager,
+ const EphyCookie *cookie)
+{
+ nsCOMPtr<nsICookieManager> cookieManager =
+ do_GetService (NS_COOKIEMANAGER_CONTRACTID);
+ if (!cookieManager) return;
+
+ nsCOMPtr<nsIIDNService> idnService
+ (do_GetService ("@mozilla.org/network/idn-service;1"));
+ NS_ENSURE_TRUE (idnService, );
+
+ nsresult rv;
+ nsCString host;
+ rv = idnService->ConvertUTF8toACE (nsCString(cookie->domain), host);
+ NS_ENSURE_SUCCESS (rv, );
+
+ cookieManager->Remove (host,
+ nsCString(cookie->name),
+ nsCString(cookie->path),
+ PR_FALSE /* block */);
+}
+
+static void
+impl_clear_cookies (EphyCookieManager *manager)
+{
+ nsCOMPtr<nsICookieManager> cookieManager =
+ do_GetService (NS_COOKIEMANAGER_CONTRACTID);
+ if (!cookieManager) return;
+
+ cookieManager->RemoveAll ();
+}
+
+static GList *
+impl_list_passwords (EphyPasswordManager *manager)
+{
+ GList *passwords = NULL;
+
+#ifndef HAVE_GECKO_1_9
+ nsresult rv;
+ nsCOMPtr<nsIPasswordManager> passwordManager =
+ do_GetService (NS_PASSWORDMANAGER_CONTRACTID);
+ if (!passwordManager) return NULL;
+
+ nsCOMPtr<nsIIDNService> idnService
+ (do_GetService ("@mozilla.org/network/idn-service;1"));
+ NS_ENSURE_TRUE (idnService, NULL);
+
+ nsCOMPtr<nsISimpleEnumerator> passwordEnumerator;
+ passwordManager->GetEnumerator (getter_AddRefs(passwordEnumerator));
+ NS_ENSURE_TRUE (passwordEnumerator, NULL);
+
+ PRBool enumResult;
+ for (passwordEnumerator->HasMoreElements(&enumResult) ;
+ enumResult == PR_TRUE ;
+ passwordEnumerator->HasMoreElements(&enumResult))
+ {
+ nsCOMPtr<nsIPassword> nsPassword;
+ passwordEnumerator->GetNext (getter_AddRefs(nsPassword));
+ if (!nsPassword) continue;
+
+ nsCString transfer;
+ rv = nsPassword->GetHost (transfer);
+ if (NS_FAILED (rv)) continue;
+
+ nsCString host;
+ idnService->ConvertACEtoUTF8 (transfer, host);
+
+ nsString unicodeName;
+ rv = nsPassword->GetUser (unicodeName);
+ if (NS_FAILED (rv)) continue;
+
+ nsCString userName;
+ NS_UTF16ToCString (unicodeName,
+ NS_CSTRING_ENCODING_UTF8, userName);
+
+ rv = nsPassword->GetPassword (unicodeName);
+ if (NS_FAILED (rv)) continue;
+
+ nsCString userPassword;
+ NS_UTF16ToCString (unicodeName,
+ NS_CSTRING_ENCODING_UTF8, userPassword);
+
+ EphyPasswordInfo *p = g_new0 (EphyPasswordInfo, 1);
+
+ p->host = g_strdup (host.get());
+ p->username = g_strdup (userName.get());
+ p->password = g_strdup (userPassword.get());
+
+ passwords = g_list_prepend (passwords, p);
+ }
+#endif /* !HAVE_GECKO_1_9 */
+
+ return passwords;
+}
+
+static void
+impl_remove_password (EphyPasswordManager *manager,
+ EphyPasswordInfo *info)
+{
+#ifndef HAVE_GECKO_1_9
+ nsCOMPtr<nsIPasswordManager> pm =
+ do_GetService (NS_PASSWORDMANAGER_CONTRACTID);
+ if (!pm) return;
+
+ nsCOMPtr<nsIIDNService> idnService
+ (do_GetService ("@mozilla.org/network/idn-service;1"));
+ NS_ENSURE_TRUE (idnService, );
+
+ nsresult rv;
+ nsCString host;
+ rv = idnService->ConvertUTF8toACE (nsCString(info->host), host);
+ NS_ENSURE_SUCCESS (rv, );
+
+ nsString userName;
+ NS_CStringToUTF16 (nsCString(info->username),
+ NS_CSTRING_ENCODING_UTF8, userName);
+ pm->RemoveUser (host, userName);
+#endif /* !HAVE_GECKO_1_9 */
+}
+
+static void
+impl_add_password (EphyPasswordManager *manager,
+ EphyPasswordInfo *info)
+{
+#ifndef HAVE_GECKO_1_9
+ nsCOMPtr<nsIPasswordManager> pm =
+ do_GetService (NS_PASSWORDMANAGER_CONTRACTID);
+ if (!pm) return;
+
+ nsCOMPtr<nsIIDNService> idnService
+ (do_GetService ("@mozilla.org/network/idn-service;1"));
+ NS_ENSURE_TRUE (idnService, );
+
+ nsresult rv;
+ nsCString host;
+ rv = idnService->ConvertUTF8toACE (nsCString(info->host), host);
+ NS_ENSURE_SUCCESS (rv, );
+
+ nsString username;
+ NS_CStringToUTF16 (nsCString(info->username),
+ NS_CSTRING_ENCODING_UTF8, username);
+
+ nsString password;
+ NS_CStringToUTF16 (nsCString(info->password),
+ NS_CSTRING_ENCODING_UTF8, password);
+
+ pm->AddUser(host, username, password);
+#endif /* !HAVE_GECKO_1_9 */
+}
+
+static void
+impl_permission_manager_add (EphyPermissionManager *manager,
+ const char *host,
+ const char *type,
+ EphyPermission permission)
+{
+ /* can only set allow or deny */
+ g_return_if_fail (permission != EPHY_PERMISSION_DEFAULT);
+ g_return_if_fail (type != NULL && type[0] != '\0');
+
+ nsCOMPtr<nsIPermissionManager> pm
+ (do_GetService (NS_PERMISSIONMANAGER_CONTRACTID));
+ if (!pm) return;
+
+ nsCOMPtr<nsIURI> uri;
+ EphyUtils::NewURI(getter_AddRefs(uri), nsCString(host));
+ if (!uri) return;
+
+ gboolean allow = (permission == EPHY_PERMISSION_ALLOWED);
+
+ pm->Add (uri, type,
+ allow ? (PRUint32) nsIPermissionManager::ALLOW_ACTION :
+ (PRUint32) nsIPermissionManager::DENY_ACTION);
+}
+
+static void
+impl_permission_manager_remove (EphyPermissionManager *manager,
+ const char *host,
+ const char *type)
+{
+ nsCOMPtr<nsIPermissionManager> pm
+ (do_GetService (NS_PERMISSIONMANAGER_CONTRACTID));
+ if (!pm) return;
+
+ pm->Remove (nsCString (host), type);
+}
+
+static void
+impl_permission_manager_clear (EphyPermissionManager *manager)
+{
+ nsCOMPtr<nsIPermissionManager> pm
+ (do_GetService (NS_PERMISSIONMANAGER_CONTRACTID));
+ if (!pm) return;
+
+ pm->RemoveAll ();
+}
+
+EphyPermission
+impl_permission_manager_test (EphyPermissionManager *manager,
+ const char *host,
+ const char *type)
+{
+ g_return_val_if_fail (type != NULL && type[0] != '\0', EPHY_PERMISSION_DEFAULT);
+
+ nsCOMPtr<nsIPermissionManager> pm
+ (do_GetService (NS_PERMISSIONMANAGER_CONTRACTID));
+ if (!pm) return EPHY_PERMISSION_DEFAULT;
+
+ nsCOMPtr<nsIURI> uri;
+ EphyUtils::NewURI(getter_AddRefs(uri), nsCString (host));
+ if (!uri) return EPHY_PERMISSION_DEFAULT;
+
+ nsresult rv;
+ PRUint32 action;
+ rv = pm->TestPermission (uri, type, &action);
+ NS_ENSURE_SUCCESS (rv, EPHY_PERMISSION_DEFAULT);
+
+ EphyPermission permission;
+
+ switch (action)
+ {
+ case nsIPermissionManager::ALLOW_ACTION:
+ permission = EPHY_PERMISSION_ALLOWED;
+ break;
+ case nsIPermissionManager::DENY_ACTION:
+ permission = EPHY_PERMISSION_DENIED;
+ break;
+ case nsIPermissionManager::UNKNOWN_ACTION:
+ default:
+ permission = EPHY_PERMISSION_DEFAULT;
+ break;
+ }
+
+ return permission;
+}
+
+GList *
+impl_permission_manager_list (EphyPermissionManager *manager,
+ const char *type)
+{
+ GList *list = NULL;
+
+ nsCOMPtr<nsIPermissionManager> pm
+ (do_GetService (NS_PERMISSIONMANAGER_CONTRACTID));
+ if (!pm) return NULL;
+
+ nsCOMPtr<nsISimpleEnumerator> pe;
+ pm->GetEnumerator(getter_AddRefs(pe));
+ NS_ENSURE_TRUE (pe, NULL);
+
+ PRBool hasMore;
+ while (NS_SUCCEEDED (pe->HasMoreElements (&hasMore)) && hasMore)
+ {
+ nsCOMPtr<nsISupports> element;
+ pe->GetNext (getter_AddRefs (element));
+
+ nsCOMPtr<nsIPermission> perm (do_QueryInterface (element));
+ if (!perm) continue;
+
+ nsresult rv;
+ nsCString str;
+ rv = perm->GetType(str);
+ if (NS_FAILED (rv)) continue;
+
+ if (strcmp (str.get(), type) == 0)
+ {
+ EphyPermissionInfo *info =
+ mozilla_permission_to_ephy_permission (perm);
+
+ if (info != NULL)
+ {
+ list = g_list_prepend (list, info);
+ }
+ }
+ }
+
+ return list;
+}
+
+static GtkWidget *
+impl_open_window (EphyEmbedSingle *single,
+ EphyEmbed *parent,
+ const char *address,
+ const char *name,
+ const char *features)
+{
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return NULL;
+
+ nsCOMPtr<nsIDOMWindow> domWindow;
+ if (parent)
+ {
+ EphyBrowser *browser;
+
+ browser = (EphyBrowser *) _mozilla_embed_get_ephy_browser (MOZILLA_EMBED(parent));
+ g_return_val_if_fail (browser != NULL, NULL);
+
+ browser->GetDOMWindow (getter_AddRefs (domWindow));
+ }
+
+ nsCOMPtr<nsIWindowWatcher> wWatch(do_GetService ("@mozilla.org/embedcomp/window-watcher;1"));
+ nsCOMPtr<nsIDOMWindow> newWindow;
+ wWatch->OpenWindow (domWindow, address, name, features, nsnull,
+ getter_AddRefs (newWindow));
+
+ return EphyUtils::FindEmbed (newWindow);
+}
+
+#ifdef ENABLE_CERTIFICATE_MANAGER
+
+static gboolean
+impl_remove_certificate (EphyCertificateManager *manager,
+ EphyX509Cert *cert)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIX509CertDB> certDB;
+ certDB = do_GetService (NS_X509CERTDB_CONTRACTID);
+ if (!certDB) return FALSE;
+
+ nsCOMPtr<nsIX509Cert> mozCert;
+ rv = mozilla_x509_cert_get_mozilla_cert (MOZILLA_X509_CERT (cert),
+ getter_AddRefs (mozCert));
+ if (NS_FAILED (rv)) return FALSE;
+
+ rv = certDB->DeleteCertificate (mozCert);
+ if (NS_FAILED (rv)) return FALSE;
+
+ return TRUE;
+}
+
+#define NICK_DELIMITER PRUnichar('\001')
+
+static GList *
+retrieveCerts (PRUint32 type)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIX509CertDB> certDB;
+ certDB = do_GetService (NS_X509CERTDB_CONTRACTID);
+ if (!certDB) return NULL;
+
+ PRUint32 count;
+ PRUnichar **certNameList = NULL;
+
+ rv = certDB->FindCertNicknames (NULL, type, &count, &certNameList);
+ if (NS_FAILED (rv)) return NULL;
+
+ LOG("Certificates found: %i", count);
+
+ GList *list = NULL;
+ for (PRUint32 i = 0; i < count; i++)
+ {
+ /* HACK HACK, this is EVIL, the string for each cert is:
+ <DELIMITER>nicknameOrEmailAddress<DELIMITER>dbKey
+ So we need to chop off the dbKey to look it up in the database.
+
+ https://bugzilla.mozilla.org/show_bug.cgi?id=214742
+ */
+ nsCString full_string;
+ NS_UTF16ToCString (nsString(certNameList[i]),
+ NS_CSTRING_ENCODING_UTF8, full_string);
+
+ const char *key = full_string.get();
+ char *pos = strrchr (key, NICK_DELIMITER);
+ if (!pos) continue;
+
+ nsCOMPtr<nsIX509Cert> mozilla_cert;
+ rv = certDB->FindCertByDBKey (pos, NULL, getter_AddRefs (mozilla_cert));
+ if (NS_FAILED (rv)) continue;
+
+ MozillaX509Cert *cert = mozilla_x509_cert_new (mozilla_cert);
+ list = g_list_prepend (list, cert);
+ }
+
+ NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY (count, certNameList);
+ return list;
+}
+
+static GList *
+impl_get_certificates (EphyCertificateManager *manager,
+ EphyX509CertType type)
+{
+ int moz_type = nsIX509Cert::USER_CERT;
+ switch (type)
+ {
+ case PERSONAL_CERTIFICATE:
+ moz_type = nsIX509Cert::USER_CERT;
+ break;
+ case SERVER_CERTIFICATE:
+ moz_type = nsIX509Cert::SERVER_CERT;
+ break;
+ case CA_CERTIFICATE:
+ moz_type = nsIX509Cert::CA_CERT;
+ break;
+ }
+ return retrieveCerts (moz_type);
+}
+
+static gboolean
+impl_import (EphyCertificateManager *manager,
+ const gchar *file)
+{
+ nsresult rv;
+ nsCOMPtr<nsIX509CertDB> certDB;
+ certDB = do_GetService (NS_X509CERTDB_CONTRACTID);
+ if (!certDB) return FALSE;
+
+ nsCOMPtr<nsILocalFile> localFile;
+ localFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
+
+ // TODO Is this correct ?
+ nsString path;
+ NS_CStringToUTF16 (nsCString(file),
+ NS_CSTRING_ENCODING_UTF8, path);
+
+
+ localFile->InitWithPath (path);
+ rv = certDB->ImportPKCS12File(NULL, localFile);
+ if (NS_FAILED (rv)) return FALSE;
+
+ return TRUE;
+}
+
+#endif /* ENABLE_CERTIFICATE_MANAGER */
+
+static void
+mozilla_embed_single_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyEmbedSingle *single = EPHY_EMBED_SINGLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_NETWORK_STATUS:
+ g_value_set_boolean (value, ephy_embed_single_get_network_status (single));
+ break;
+ }
+}
+
+static void
+mozilla_embed_single_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyEmbedSingle *single = EPHY_EMBED_SINGLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_NETWORK_STATUS:
+ ephy_embed_single_set_network_status (single, g_value_get_boolean (value));
+ break;
+ }
+}
+static void
+mozilla_embed_single_class_init (MozillaEmbedSingleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
+
+ object_class->dispose = mozilla_embed_single_dispose;
+ object_class->finalize = mozilla_embed_single_finalize;
+ object_class->get_property = mozilla_embed_single_get_property;
+ object_class->set_property = mozilla_embed_single_set_property;
+
+ g_object_class_override_property (object_class, PROP_NETWORK_STATUS, "network-status");
+
+ g_type_class_add_private (object_class, sizeof (MozillaEmbedSinglePrivate));
+}
+
+static void
+ephy_embed_single_iface_init (EphyEmbedSingleIface *iface)
+{
+ iface->init = impl_init;
+ iface->clear_cache = impl_clear_cache;
+ iface->clear_auth_cache = impl_clear_auth_cache;
+ iface->set_network_status = impl_set_network_status;
+ iface->get_network_status = impl_get_network_status;
+ iface->get_font_list = impl_get_font_list;
+ iface->open_window = impl_open_window;
+ iface->get_backend_name = impl_get_backend_name;
+}
+
+static void
+ephy_cookie_manager_iface_init (EphyCookieManagerIface *iface)
+{
+ iface->list = impl_list_cookies;
+ iface->remove = impl_remove_cookie;
+ iface->clear = impl_clear_cookies;
+}
+
+static void
+ephy_password_manager_iface_init (EphyPasswordManagerIface *iface)
+{
+ iface->add = impl_add_password;
+ iface->remove = impl_remove_password;
+ iface->list = impl_list_passwords;
+}
+
+static void
+ephy_permission_manager_iface_init (EphyPermissionManagerIface *iface)
+{
+ iface->add = impl_permission_manager_add;
+ iface->remove = impl_permission_manager_remove;
+ iface->clear = impl_permission_manager_clear;
+ iface->test = impl_permission_manager_test;
+ iface->list = impl_permission_manager_list;
+}
+
+#ifdef ENABLE_CERTIFICATE_MANAGER
+
+static void
+ephy_certificate_manager_iface_init (EphyCertificateManagerIface *iface)
+{
+ iface->get_certificates = impl_get_certificates;
+ iface->remove_certificate = impl_remove_certificate;
+ iface->import = impl_import;
+}
+
+#endif /* ENABLE_CERTIFICATE_MANAGER */
diff --git a/embed/xulrunner/embed/mozilla-embed-single.h b/embed/xulrunner/embed/mozilla-embed-single.h
new file mode 100644
index 000000000..960b6eb5b
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-embed-single.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2000-2003 Marco Pesenti Gritti
+ * Copyright © 2003 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef MOZILLA_EMBED_SINGLE_H
+#define MOZILLA_EMBED_SINGLE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MOZILLA_TYPE_EMBED_SINGLE (mozilla_embed_single_get_type ())
+#define MOZILLA_EMBED_SINGLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MOZILLA_TYPE_EMBED_SINGLE, MozillaEmbedSingle))
+#define MOZILLA_EMBED_SINGLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MOZILLA_TYPE_EMBED_SINGLE, MozillaEmbedSingleClass))
+#define MOZILLA_IS_EMBED_SINGLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MOZILLA_TYPE_EMBED_SINGLE))
+#define MOZILLA_IS_EMBED_SINGLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MOZILLA_TYPE_EMBED_SINGLE))
+#define MOZILLA_EMBED_SINGLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MOZILLA_TYPE_EMBED_SINGLE, MozillaEmbedSingleClass))
+
+typedef struct MozillaEmbedSingle MozillaEmbedSingle;
+typedef struct MozillaEmbedSingleClass MozillaEmbedSingleClass;
+typedef struct MozillaEmbedSinglePrivate MozillaEmbedSinglePrivate;
+
+struct MozillaEmbedSingle
+{
+ GObject parent;
+
+ /*< private >*/
+ MozillaEmbedSinglePrivate *priv;
+};
+
+struct MozillaEmbedSingleClass
+{
+ GObjectClass parent_class;
+};
+
+GType mozilla_embed_single_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/embed/xulrunner/embed/mozilla-embed.cpp b/embed/xulrunner/embed/mozilla-embed.cpp
new file mode 100644
index 000000000..854299c46
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-embed.cpp
@@ -0,0 +1,1273 @@
+/*
+ * Copyright © 2000-2004 Marco Pesenti Gritti
+ * Copyright © 2003, 2004 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <nsStringAPI.h>
+
+#include <nsIDOMKeyEvent.h>
+#include <nsIDOMMouseEvent.h>
+#include <nsIRequest.h>
+#include <nsIURI.h>
+#include <nsIWebNavigation.h>
+#include <nsIWebProgressListener.h>
+#include <nsMemory.h>
+
+#include "EphyBrowser.h"
+#include "EphyUtils.h"
+#include "EventContext.h"
+
+#include "gecko-dom-event.h"
+#include "gecko-dom-event-internal.h"
+
+#include "ephy-command-manager.h"
+#include "ephy-debug.h"
+#include "ephy-embed-shell.h"
+#include "ephy-embed-single.h"
+#include "ephy-string.h"
+#include "mozilla-embed-event.h"
+
+#include "mozilla-embed.h"
+
+static void mozilla_embed_class_init (MozillaEmbedClass *klass);
+static void mozilla_embed_init (MozillaEmbed *gs);
+static void mozilla_embed_destroy (GtkObject *object);
+static void mozilla_embed_finalize (GObject *object);
+static void ephy_embed_iface_init (EphyEmbedIface *iface);
+
+static void mozilla_embed_location_changed_cb (GeckoEmbed *embed,
+ MozillaEmbed *membed);
+static void mozilla_embed_net_state_all_cb (GeckoEmbed *embed,
+ const char *aURI,
+ gint state,
+ guint status,
+ MozillaEmbed *membed);
+static gboolean mozilla_embed_dom_mouse_click_cb(GeckoEmbed *embed,
+ GeckoDOMEvent *dom_event,
+ MozillaEmbed *membed);
+static gboolean mozilla_embed_dom_mouse_down_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *dom_event,
+ MozillaEmbed *membed);
+static gboolean mozilla_embed_dom_key_press_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *dom_event,
+ MozillaEmbed *membed);
+static void mozilla_embed_new_window_cb (GeckoEmbed *embed,
+ GeckoEmbed **newEmbed,
+ guint chrome_mask,
+ MozillaEmbed *membed);
+static void mozilla_embed_security_change_cb (GeckoEmbed *embed,
+ gpointer request,
+ PRUint32 state,
+ MozillaEmbed *membed);
+static EphyEmbedSecurityLevel mozilla_embed_security_level (PRUint32 state);
+
+#define MOZILLA_EMBED_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), MOZILLA_TYPE_EMBED, MozillaEmbedPrivate))
+
+typedef enum
+{
+ MOZILLA_EMBED_LOAD_STARTED,
+ MOZILLA_EMBED_LOAD_REDIRECTING,
+ MOZILLA_EMBED_LOAD_LOADING,
+ MOZILLA_EMBED_LOAD_STOPPED
+} MozillaEmbedLoadState;
+
+struct MozillaEmbedPrivate
+{
+ EphyBrowser *browser;
+ MozillaEmbedLoadState load_state;
+};
+
+#define WINDOWWATCHER_CONTRACTID "@mozilla.org/embedcomp/window-watcher;1"
+
+static GObjectClass *parent_class = NULL;
+
+static void
+impl_manager_do_command (EphyCommandManager *manager,
+ const char *command)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(manager)->priv;
+
+ mpriv->browser->DoCommand (command);
+}
+
+static gboolean
+impl_manager_can_do_command (EphyCommandManager *manager,
+ const char *command)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(manager)->priv;
+ nsresult rv;
+ PRBool enabled;
+
+ rv = mpriv->browser->GetCommandState (command, &enabled);
+
+ return NS_SUCCEEDED (rv) ? enabled : FALSE;
+}
+
+static void
+ephy_command_manager_iface_init (EphyCommandManagerIface *iface)
+{
+ iface->do_command = impl_manager_do_command;
+ iface->can_do_command = impl_manager_can_do_command;
+}
+
+GType
+mozilla_embed_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ const GTypeInfo our_info =
+ {
+ sizeof (MozillaEmbedClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) mozilla_embed_class_init,
+ NULL,
+ NULL, /* class_data */
+ sizeof (MozillaEmbed),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mozilla_embed_init
+ };
+
+ const GInterfaceInfo embed_info =
+ {
+ (GInterfaceInitFunc) ephy_embed_iface_init,
+ NULL,
+ NULL
+ };
+
+ const GInterfaceInfo ephy_command_manager_info =
+ {
+ (GInterfaceInitFunc) ephy_command_manager_iface_init,
+ NULL,
+ NULL
+ };
+
+ type = g_type_register_static (GECKO_TYPE_EMBED,
+ "MozillaEmbed",
+ &our_info,
+ (GTypeFlags)0);
+ g_type_add_interface_static (type,
+ EPHY_TYPE_EMBED,
+ &embed_info);
+ g_type_add_interface_static (type,
+ EPHY_TYPE_COMMAND_MANAGER,
+ &ephy_command_manager_info);
+ }
+
+ return type;
+}
+
+static void
+mozilla_embed_grab_focus (GtkWidget *widget)
+{
+ GtkWidget *child;
+
+ child = gtk_bin_get_child (GTK_BIN (widget));
+
+ if (child != NULL)
+ {
+ gtk_widget_grab_focus (child);
+ }
+ else
+ {
+ g_warning ("Need to realize the embed before grabbing focus!\n");
+ }
+}
+
+static void
+impl_close (EphyEmbed *embed)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED (embed)->priv;
+
+ mpriv->browser->Close ();
+}
+
+static void
+mozilla_embed_realize (GtkWidget *widget)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED (widget)->priv;
+
+ GTK_WIDGET_CLASS (parent_class)->realize (widget);
+
+ /* Initialise our helper class */
+ nsresult rv;
+ rv = mpriv->browser->Init (GECKO_EMBED (widget));
+ if (NS_FAILED (rv))
+ {
+ g_warning ("EphyBrowser initialization failed for %p\n", widget);
+ return;
+ }
+}
+
+static GObject *
+mozilla_embed_constructor (GType type, guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ g_object_ref (embed_shell);
+
+ /* we depend on single because of mozilla initialization */
+ ephy_embed_shell_get_embed_single (embed_shell);
+
+ return parent_class->constructor (type, n_construct_properties,
+ construct_params);
+}
+
+static void
+mozilla_embed_class_init (MozillaEmbedClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
+
+ object_class->constructor = mozilla_embed_constructor;
+ object_class->finalize = mozilla_embed_finalize;
+
+ gtk_object_class->destroy = mozilla_embed_destroy;
+
+ widget_class->grab_focus = mozilla_embed_grab_focus;
+ widget_class->realize = mozilla_embed_realize;
+
+ g_type_class_add_private (object_class, sizeof(MozillaEmbedPrivate));
+}
+
+static void
+mozilla_embed_init (MozillaEmbed *embed)
+{
+ embed->priv = MOZILLA_EMBED_GET_PRIVATE (embed);
+ embed->priv->browser = new EphyBrowser ();
+
+ g_signal_connect_object (embed, "location",
+ G_CALLBACK (mozilla_embed_location_changed_cb),
+ embed, (GConnectFlags) 0);
+ g_signal_connect_object (embed, "net_state_all",
+ G_CALLBACK (mozilla_embed_net_state_all_cb),
+ embed, (GConnectFlags) 0);
+ g_signal_connect_object (embed, "dom_mouse_click",
+ G_CALLBACK (mozilla_embed_dom_mouse_click_cb),
+ embed, (GConnectFlags) 0);
+ g_signal_connect_object (embed, "dom_mouse_down",
+ G_CALLBACK (mozilla_embed_dom_mouse_down_cb),
+ embed, (GConnectFlags) 0);
+ g_signal_connect_object (embed, "dom-key-press",
+ G_CALLBACK (mozilla_embed_dom_key_press_cb),
+ embed, (GConnectFlags) 0);
+ g_signal_connect_object (embed, "new_window",
+ G_CALLBACK (mozilla_embed_new_window_cb),
+ embed, (GConnectFlags) 0);
+ g_signal_connect_object (embed, "security_change",
+ G_CALLBACK (mozilla_embed_security_change_cb),
+ embed, (GConnectFlags) 0);
+}
+
+gpointer
+_mozilla_embed_get_ephy_browser (MozillaEmbed *embed)
+{
+ g_return_val_if_fail (embed->priv->browser != NULL, NULL);
+
+ return embed->priv->browser;
+}
+
+static void
+mozilla_embed_destroy (GtkObject *object)
+{
+ MozillaEmbed *embed = MOZILLA_EMBED (object);
+
+ if (embed->priv->browser)
+ {
+ embed->priv->browser->Destroy();
+ }
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+mozilla_embed_finalize (GObject *object)
+{
+ MozillaEmbed *embed = MOZILLA_EMBED (object);
+
+ if (embed->priv->browser)
+ {
+ delete embed->priv->browser;
+ embed->priv->browser = nsnull;
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+
+ g_object_unref (embed_shell);
+}
+
+static void
+impl_load_url (EphyEmbed *embed,
+ const char *url)
+{
+ gecko_embed_load_url (GECKO_EMBED (embed), url);
+}
+
+static char * impl_get_location (EphyEmbed *embed, gboolean toplevel);
+
+static void
+impl_load (EphyEmbed *embed,
+ const char *url,
+ EphyEmbedLoadFlags flags,
+ EphyEmbed *preview_embed)
+{
+ EphyBrowser *browser;
+
+ browser = MOZILLA_EMBED(embed)->priv->browser;
+ g_return_if_fail (browser != NULL);
+
+ nsCOMPtr<nsIURI> uri;
+ if (preview_embed != NULL)
+ {
+ EphyBrowser *pbrowser;
+
+ pbrowser = MOZILLA_EMBED(preview_embed)->priv->browser;
+ if (pbrowser != NULL)
+ {
+ pbrowser->GetDocumentURI (getter_AddRefs (uri));
+ }
+ }
+
+#ifdef HAVE_GECKO_1_8_1
+ if (flags & EPHY_EMBED_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP)
+ {
+ browser->LoadURI (url, nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP, uri);
+ }
+ else
+#endif /* HAVE_GECKO_1_8_1 */
+ {
+ browser->LoadURI (url, nsIWebNavigation::LOAD_FLAGS_NONE, uri);
+ }
+}
+
+static void
+impl_stop_load (EphyEmbed *embed)
+{
+ gecko_embed_stop_load (GECKO_EMBED(embed));
+}
+
+static gboolean
+impl_can_go_back (EphyEmbed *embed)
+{
+ return gecko_embed_can_go_back (GECKO_EMBED(embed));
+}
+
+static gboolean
+impl_can_go_forward (EphyEmbed *embed)
+{
+ return gecko_embed_can_go_forward (GECKO_EMBED(embed));
+}
+
+static gboolean
+mozilla_embed_get_uri_parent (MozillaEmbed *membed,
+ const char *aUri,
+ nsCString &aParent)
+{
+ nsresult rv;
+ nsCString encoding;
+ rv = membed->priv->browser->GetEncoding (encoding);
+ if (NS_FAILED (rv)) return FALSE;
+
+ nsCOMPtr<nsIURI> uri;
+ rv = EphyUtils::NewURI (getter_AddRefs(uri), nsCString(aUri), encoding.get());
+ if (NS_FAILED(rv) || !uri) return FALSE;
+
+ /* Don't support going 'up' with chrome url's, mozilla handily
+ * fixes them up for us, so it doesn't work properly, see
+ * rdf/chrome/src/nsChromeProtocolHandler.cpp::NewURI()
+ * (the Canonify() call)
+ */
+ nsCString scheme;
+ rv = uri->GetScheme (scheme);
+ if (NS_FAILED(rv) || !scheme.Length()) return FALSE;
+ if (strcmp (scheme.get(), "chrome") == 0) return FALSE;
+
+ nsCString path;
+ rv = uri->GetPath(path);
+ if (NS_FAILED(rv) || !path.Length()) return FALSE;
+ if (strcmp (path.get (), "/") == 0) return FALSE;
+
+ const char *slash = strrchr (path.BeginReading(), '/');
+ if (!slash) return FALSE;
+
+ if (slash[1] == '\0')
+ {
+ /* ends with a slash - a directory, go to parent */
+ rv = uri->Resolve (nsCString(".."), aParent);
+ }
+ else
+ {
+ /* it's a file, go to the directory */
+ rv = uri->Resolve (nsCString("."), aParent);
+ }
+
+ return NS_SUCCEEDED (rv);
+}
+
+static gboolean
+impl_can_go_up (EphyEmbed *embed)
+{
+ MozillaEmbed *membed = MOZILLA_EMBED (embed);
+ char *address;
+ gboolean result;
+
+ address = ephy_embed_get_location (embed, TRUE);
+ if (address == NULL) return FALSE;
+
+ nsCString parent;
+ result = mozilla_embed_get_uri_parent (membed, address, parent);
+ g_free (address);
+
+ return result;
+}
+
+static GSList *
+impl_get_go_up_list (EphyEmbed *embed)
+{
+ MozillaEmbed *membed = MOZILLA_EMBED (embed);
+ GSList *l = NULL;
+ char *address, *s;
+
+ address = ephy_embed_get_location (embed, TRUE);
+ if (address == NULL) return NULL;
+
+ s = address;
+ nsCString parent;
+ while (mozilla_embed_get_uri_parent (membed, s, parent))
+ {
+ s = g_strdup (parent.get());
+ l = g_slist_prepend (l, s);
+ }
+
+ g_free (address);
+
+ return g_slist_reverse (l);
+}
+
+static void
+impl_go_back (EphyEmbed *embed)
+{
+ gecko_embed_go_back (GECKO_EMBED(embed));
+}
+
+static void
+impl_go_forward (EphyEmbed *embed)
+{
+ gecko_embed_go_forward (GECKO_EMBED(embed));
+}
+
+static void
+impl_go_up (EphyEmbed *embed)
+{
+ MozillaEmbed *membed = MOZILLA_EMBED (embed);
+ char *uri;
+
+ uri = ephy_embed_get_location (embed, TRUE);
+ if (uri == NULL) return;
+
+ gboolean rv;
+ nsCString parent_uri;
+ rv = mozilla_embed_get_uri_parent (membed, uri, parent_uri);
+ g_free (uri);
+
+ g_return_if_fail (rv != FALSE);
+
+ ephy_embed_load_url (embed, parent_uri.get ());
+}
+
+static char *
+impl_get_title (EphyEmbed *embed)
+{
+ return gecko_embed_get_title (GECKO_EMBED (embed));
+}
+
+static char *
+impl_get_link_message (EphyEmbed *embed)
+{
+ return gecko_embed_get_link_message (GECKO_EMBED (embed));
+}
+
+static char *
+impl_get_js_status (EphyEmbed *embed)
+{
+ return gecko_embed_get_js_status (GECKO_EMBED (embed));
+}
+
+static char *
+impl_get_location (EphyEmbed *embed,
+ gboolean toplevel)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+ nsresult rv;
+
+ nsCOMPtr<nsIURI> uri;
+ if (toplevel)
+ {
+ rv = mpriv->browser->GetDocumentURI (getter_AddRefs (uri));
+ }
+ else
+ {
+ rv = mpriv->browser->GetTargetDocumentURI (getter_AddRefs (uri));
+ }
+
+ if (NS_FAILED (rv)) return NULL;
+
+ nsCOMPtr<nsIURI> furi;
+ rv = uri->Clone (getter_AddRefs (furi));
+ /* Some nsIURI impls return NS_OK even though they didn't put anything in the outparam!! */
+ if (NS_FAILED (rv) || !furi) furi.swap(uri);
+
+ /* Hide password part */
+ nsCString user;
+ furi->GetUsername (user);
+ furi->SetUserPass (user);
+
+ nsCString url;
+ furi->GetSpec (url);
+
+ return url.Length() ? g_strdup (url.get()) : NULL;
+}
+
+static void
+impl_reload (EphyEmbed *embed,
+ gboolean force)
+{
+ guint32 mflags = GECKO_EMBED_FLAG_RELOADNORMAL;
+
+ if (force)
+ {
+ mflags = GECKO_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE;
+ }
+
+ gecko_embed_reload (GECKO_EMBED(embed), mflags);
+}
+
+static void
+impl_set_zoom (EphyEmbed *embed,
+ float zoom)
+{
+ EphyBrowser *browser;
+ nsresult rv;
+
+ g_return_if_fail (zoom > 0.0);
+
+ browser = MOZILLA_EMBED(embed)->priv->browser;
+ g_return_if_fail (browser != NULL);
+
+ rv = browser->SetZoom (zoom);
+
+ if (NS_SUCCEEDED (rv))
+ {
+ g_signal_emit_by_name (embed, "ge_zoom_change", zoom);
+ }
+}
+
+static float
+impl_get_zoom (EphyEmbed *embed)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+ float f;
+
+ nsresult rv;
+ rv = mpriv->browser->GetZoom (&f);
+
+ if (NS_SUCCEEDED (rv))
+ {
+ return f;
+ }
+
+ return 1.0;
+}
+
+static void
+impl_scroll_lines (EphyEmbed *embed,
+ int num_lines)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+
+ mpriv->browser->ScrollLines (num_lines);
+}
+
+static void
+impl_scroll_pages (EphyEmbed *embed,
+ int num_pages)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+
+ mpriv->browser->ScrollPages (num_pages);
+}
+
+static void
+impl_scroll_pixels (EphyEmbed *embed,
+ int dx,
+ int dy)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+
+ mpriv->browser->ScrollPixels (dx, dy);
+}
+
+static int
+impl_shistory_n_items (EphyEmbed *embed)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+ nsresult rv;
+ int count, index;
+
+ rv = mpriv->browser->GetSHInfo (&count, &index);
+
+ return NS_SUCCEEDED(rv) ? count : 0;
+}
+
+static void
+impl_shistory_get_nth (EphyEmbed *embed,
+ int nth,
+ gboolean is_relative,
+ char **aUrl,
+ char **aTitle)
+{
+ nsresult rv;
+ nsCString url;
+ PRUnichar *title;
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+
+ if (is_relative)
+ {
+ nth += ephy_embed_shistory_get_pos (embed);
+ }
+
+ rv = mpriv->browser->GetSHUrlAtIndex(nth, url);
+
+ *aUrl = (NS_SUCCEEDED (rv) && url.Length()) ? g_strdup(url.get()) : NULL;
+
+ rv = mpriv->browser->GetSHTitleAtIndex(nth, &title);
+
+ if (title)
+ {
+ nsCString cTitle;
+ NS_UTF16ToCString (nsString(title),
+ NS_CSTRING_ENCODING_UTF8, cTitle);
+ *aTitle = g_strdup (cTitle.get());
+ nsMemory::Free (title);
+ }
+ else
+ {
+ *aTitle = NULL;
+ }
+}
+
+static int
+impl_shistory_get_pos (EphyEmbed *embed)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+ nsresult rv;
+ int count, index;
+
+ rv = mpriv->browser->GetSHInfo (&count, &index);
+
+ return NS_SUCCEEDED(rv) ? index : 0;
+}
+
+static void
+impl_shistory_go_nth (EphyEmbed *embed,
+ int nth)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+
+ mpriv->browser->GoToHistoryIndex (nth);
+}
+
+static void
+impl_shistory_copy (EphyEmbed *source,
+ EphyEmbed *dest,
+ gboolean copy_back,
+ gboolean copy_forward,
+ gboolean copy_current)
+{
+ MozillaEmbedPrivate *spriv = MOZILLA_EMBED(source)->priv;
+ MozillaEmbedPrivate *dpriv = MOZILLA_EMBED(dest)->priv;
+
+ spriv->browser->CopySHistory(dpriv->browser, copy_back,
+ copy_forward, copy_current);
+}
+
+static void
+impl_get_security_level (EphyEmbed *embed,
+ EphyEmbedSecurityLevel *level,
+ char **description)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED (embed)->priv;
+
+ if (level) *level = EPHY_EMBED_STATE_IS_UNKNOWN;
+ if (description) *description = NULL;
+
+ nsresult rv;
+ PRUint32 state;
+ nsCString desc;
+ rv = mpriv->browser->GetSecurityInfo (&state, desc);
+ if (NS_FAILED (rv)) return;
+
+ if (level) *level = mozilla_embed_security_level (state);
+ if (description) *description = g_strdup (desc.get());
+}
+
+static void
+impl_show_page_certificate (EphyEmbed *embed)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED (embed)->priv;
+
+ mpriv->browser->ShowCertificate ();
+}
+
+static void
+impl_print (EphyEmbed *embed)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+
+ mpriv->browser->Print ();
+}
+
+static void
+impl_set_print_preview_mode (EphyEmbed *embed, gboolean preview_mode)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+
+ mpriv->browser->SetPrintPreviewMode (preview_mode);
+}
+
+static int
+impl_print_preview_n_pages (EphyEmbed *embed)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+ nsresult rv;
+ int num;
+
+ rv = mpriv->browser->PrintPreviewNumPages(&num);
+
+ return NS_SUCCEEDED (rv) ? num : 0;
+}
+
+static void
+impl_print_preview_navigate (EphyEmbed *embed,
+ EphyEmbedPrintPreviewNavType type,
+ int page)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+
+ mpriv->browser->PrintPreviewNavigate(type, page);
+}
+
+static void
+impl_set_encoding (EphyEmbed *embed,
+ const char *encoding)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+ nsresult rv;
+ nsCString currEnc;
+
+ g_return_if_fail (encoding != NULL);
+
+ rv = mpriv->browser->GetEncoding (currEnc);
+ if (NS_FAILED (rv)) return;
+
+ if (strcmp (currEnc.get(), encoding) != 0 ||
+ encoding[0] == '\0' && !ephy_embed_has_automatic_encoding (embed))
+ {
+ rv = mpriv->browser->ForceEncoding (encoding);
+ if (NS_FAILED (rv)) return;
+ }
+
+ gecko_embed_reload (GECKO_EMBED (embed),
+ GECKO_EMBED_FLAG_RELOADCHARSETCHANGE);
+}
+
+static char *
+impl_get_encoding (EphyEmbed *embed)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+ nsresult rv;
+ nsCString encoding;
+
+ rv = mpriv->browser->GetEncoding (encoding);
+
+ if (NS_FAILED (rv) || !encoding.Length())
+ {
+ return NULL;
+ }
+
+ return g_strdup (encoding.get());
+}
+
+static gboolean
+impl_has_automatic_encoding (EphyEmbed *embed)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+ nsresult rv;
+ nsCString encoding;
+
+ rv = mpriv->browser->GetForcedEncoding (encoding);
+
+ if (NS_FAILED (rv) || !encoding.Length())
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+impl_has_modified_forms (EphyEmbed *embed)
+{
+ MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
+ nsresult rv;
+
+ PRBool modified;
+ rv = mpriv->browser->GetHasModifiedForms (&modified);
+
+ return NS_SUCCEEDED (rv) ? modified : FALSE;
+}
+
+static void
+mozilla_embed_location_changed_cb (GeckoEmbed *embed,
+ MozillaEmbed *membed)
+{
+ char *location;
+
+ location = gecko_embed_get_location (embed);
+ g_signal_emit_by_name (membed, "ge-location", location);
+ g_free (location);
+}
+
+static void
+update_load_state (MozillaEmbed *membed, gint state)
+{
+ MozillaEmbedPrivate *priv = membed->priv;
+
+ if (state & GECKO_EMBED_FLAG_IS_DOCUMENT &&
+ state & (GECKO_EMBED_FLAG_START | GECKO_EMBED_FLAG_STOP))
+ {
+ g_signal_emit_by_name (membed, "ge-document-type",
+ priv->browser->GetDocumentType ());
+ }
+
+ if (state & GECKO_EMBED_FLAG_RESTORING &&
+ priv->load_state == MOZILLA_EMBED_LOAD_STARTED)
+ {
+ priv->load_state = MOZILLA_EMBED_LOAD_LOADING;
+
+ char *address;
+ address = gecko_embed_get_location (GECKO_EMBED (membed));
+ g_signal_emit_by_name (membed, "ge-content-change", address);
+ g_free (address);
+ }
+
+ if (state & GECKO_EMBED_FLAG_IS_NETWORK)
+ {
+ if (state & GECKO_EMBED_FLAG_START)
+ {
+ priv->load_state = MOZILLA_EMBED_LOAD_STARTED;
+ }
+ else if (state & GECKO_EMBED_FLAG_STOP)
+ {
+ priv->load_state = MOZILLA_EMBED_LOAD_STOPPED;
+ }
+ }
+ else if (state & GECKO_EMBED_FLAG_START &&
+ state & GECKO_EMBED_FLAG_IS_REQUEST)
+ {
+ if (priv->load_state == MOZILLA_EMBED_LOAD_REDIRECTING)
+ {
+ priv->load_state = MOZILLA_EMBED_LOAD_STARTED;
+ }
+ else if (priv->load_state != MOZILLA_EMBED_LOAD_LOADING)
+ {
+ priv->load_state = MOZILLA_EMBED_LOAD_LOADING;
+
+ char *address;
+ address = gecko_embed_get_location (GECKO_EMBED (membed));
+ g_signal_emit_by_name (membed, "ge_content_change", address);
+ g_free (address);
+ }
+ }
+ else if (state & GECKO_EMBED_FLAG_REDIRECTING &&
+ priv->load_state == MOZILLA_EMBED_LOAD_STARTED)
+ {
+ priv->load_state = MOZILLA_EMBED_LOAD_REDIRECTING;
+ }
+}
+
+static void
+mozilla_embed_net_state_all_cb (GeckoEmbed *embed, const char *aURI,
+ gint state, guint status,
+ MozillaEmbed *membed)
+{
+ EphyEmbedNetState estate = EPHY_EMBED_STATE_UNKNOWN;
+ int i;
+
+ struct
+ {
+ guint state;
+ EphyEmbedNetState embed_state;
+ }
+ conversion_map [] =
+ {
+ { GECKO_EMBED_FLAG_START, EPHY_EMBED_STATE_START },
+ { GECKO_EMBED_FLAG_STOP, EPHY_EMBED_STATE_STOP },
+ { GECKO_EMBED_FLAG_REDIRECTING, EPHY_EMBED_STATE_REDIRECTING },
+ { GECKO_EMBED_FLAG_TRANSFERRING, EPHY_EMBED_STATE_TRANSFERRING },
+ { GECKO_EMBED_FLAG_NEGOTIATING, EPHY_EMBED_STATE_NEGOTIATING },
+ { GECKO_EMBED_FLAG_IS_REQUEST, EPHY_EMBED_STATE_IS_REQUEST },
+ { GECKO_EMBED_FLAG_IS_DOCUMENT, EPHY_EMBED_STATE_IS_DOCUMENT },
+ { GECKO_EMBED_FLAG_IS_NETWORK, EPHY_EMBED_STATE_IS_NETWORK },
+ { GECKO_EMBED_FLAG_RESTORING, EPHY_EMBED_STATE_RESTORING },
+ { 0, EPHY_EMBED_STATE_UNKNOWN }
+ };
+
+ for (i = 0; conversion_map[i].state != 0; i++)
+ {
+ if (state & conversion_map[i].state)
+ {
+ estate = (EphyEmbedNetState) (estate | conversion_map[i].embed_state);
+ }
+ }
+
+ update_load_state (membed, state);
+
+ g_signal_emit_by_name (membed, "ge_net_state", aURI, /* FIXME: (gulong) */ estate);
+}
+
+static gboolean
+mozilla_embed_emit_mouse_signal (MozillaEmbed *embed,
+ GeckoDOMEvent *dom_event,
+ const char *signal_name)
+{
+ MozillaEmbedPrivate *mpriv = embed->priv;
+ MozillaEmbedEvent *info;
+ EventContext event_context;
+ gint return_value = FALSE;
+ nsresult rv;
+
+ if (dom_event == NULL) return FALSE;
+
+ nsCOMPtr<nsIDOMEvent> domEvent (gecko_dom_event_get_I (dom_event));
+ nsCOMPtr<nsIDOMMouseEvent> ev (do_QueryInterface (domEvent));
+ NS_ENSURE_TRUE (ev, FALSE);
+ nsCOMPtr<nsIDOMEvent> dev = do_QueryInterface (ev);
+ NS_ENSURE_TRUE (dev, FALSE);
+
+ info = mozilla_embed_event_new (static_cast<gpointer>(dev));
+
+ event_context.Init (mpriv->browser);
+ rv = event_context.GetMouseEventInfo (ev, MOZILLA_EMBED_EVENT (info));
+ if (NS_FAILED (rv))
+ {
+ g_object_unref (info);
+ return FALSE;
+ }
+
+ nsCOMPtr<nsIDOMDocument> domDoc;
+ rv = event_context.GetTargetDocument (getter_AddRefs(domDoc));
+ if (NS_SUCCEEDED (rv))
+ {
+ mpriv->browser->PushTargetDocument (domDoc);
+
+ g_signal_emit_by_name (embed, signal_name,
+ info, &return_value);
+ mpriv->browser->PopTargetDocument ();
+ }
+
+ g_object_unref (info);
+
+ return return_value;
+}
+
+static gboolean
+mozilla_embed_dom_mouse_click_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *dom_event,
+ MozillaEmbed *membed)
+{
+ return mozilla_embed_emit_mouse_signal (membed, dom_event,
+ "ge_dom_mouse_click");
+}
+
+static gboolean
+mozilla_embed_dom_mouse_down_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *dom_event,
+ MozillaEmbed *membed)
+{
+ return mozilla_embed_emit_mouse_signal (membed, dom_event,
+ "ge_dom_mouse_down");
+}
+
+static gint
+mozilla_embed_dom_key_press_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *dom_event,
+ MozillaEmbed *membed)
+{
+ gint retval = FALSE;
+
+ if (dom_event == NULL) return FALSE;
+
+ nsCOMPtr<nsIDOMEvent> domEvent (gecko_dom_event_get_I (dom_event));
+ nsCOMPtr<nsIDOMKeyEvent> ev (do_QueryInterface (domEvent));
+ NS_ENSURE_TRUE (ev, FALSE);
+
+ if (!EventContext::CheckKeyPress (ev)) return FALSE;
+
+ GdkEvent *event = gtk_get_current_event ();
+ if (event == NULL) return FALSE; /* shouldn't happen! */
+
+ g_return_val_if_fail (GDK_KEY_PRESS == event->type, FALSE);
+
+ g_signal_emit_by_name (embed, "ge-search-key-press", event, &retval);
+
+ gdk_event_free (event);
+
+ return retval;
+}
+
+EphyEmbedChrome
+_mozilla_embed_translate_chrome (GeckoEmbedChromeFlags flags)
+{
+ static const struct
+ {
+ guint mozilla_flag;
+ guint ephy_flag;
+ }
+ conversion_map [] =
+ {
+ { GECKO_EMBED_FLAG_MENUBARON, EPHY_EMBED_CHROME_MENUBAR },
+ { GECKO_EMBED_FLAG_TOOLBARON, EPHY_EMBED_CHROME_TOOLBAR },
+ { GECKO_EMBED_FLAG_STATUSBARON, EPHY_EMBED_CHROME_STATUSBAR },
+ { GECKO_EMBED_FLAG_PERSONALTOOLBARON, EPHY_EMBED_CHROME_BOOKMARKSBAR },
+ };
+
+ guint mask = 0, i;
+
+ for (i = 0; i < G_N_ELEMENTS (conversion_map); i++)
+ {
+ if (flags & conversion_map[i].mozilla_flag)
+ {
+ mask |= conversion_map[i].ephy_flag;
+ }
+ }
+
+ return (EphyEmbedChrome) mask;
+}
+
+static void
+mozilla_embed_new_window_cb (GeckoEmbed *embed,
+ GeckoEmbed **newEmbed,
+ guint chrome_mask,
+ MozillaEmbed *membed)
+{
+ GeckoEmbedChromeFlags chrome = (GeckoEmbedChromeFlags) chrome_mask;
+ EphyEmbed *new_embed = NULL;
+ GObject *single;
+ EphyEmbedChrome mask;
+
+ if (chrome & GECKO_EMBED_FLAG_OPENASCHROME)
+ {
+ *newEmbed = _mozilla_embed_new_xul_dialog ();
+ return;
+ }
+
+ mask = _mozilla_embed_translate_chrome (chrome);
+
+ single = ephy_embed_shell_get_embed_single (embed_shell);
+ g_signal_emit_by_name (single, "new-window", embed, mask,
+ &new_embed);
+
+ g_assert (new_embed != NULL);
+
+ gecko_embed_set_chrome_mask (GECKO_EMBED (new_embed), chrome);
+
+ g_signal_emit_by_name (membed, "ge-new-window", new_embed);
+
+ *newEmbed = GECKO_EMBED (new_embed);
+}
+
+static void
+mozilla_embed_security_change_cb (GeckoEmbed *embed,
+ gpointer requestptr,
+ PRUint32 state,
+ MozillaEmbed *membed)
+{
+ g_signal_emit_by_name (membed, "ge_security_change",
+ mozilla_embed_security_level (state));
+}
+
+static EphyEmbedSecurityLevel
+mozilla_embed_security_level (PRUint32 state)
+{
+ EphyEmbedSecurityLevel level;
+
+ switch (state)
+ {
+ case nsIWebProgressListener::STATE_IS_INSECURE:
+ level = EPHY_EMBED_STATE_IS_INSECURE;
+ break;
+ case nsIWebProgressListener::STATE_IS_BROKEN:
+ level = EPHY_EMBED_STATE_IS_BROKEN;
+ break;
+ case nsIWebProgressListener::STATE_IS_SECURE|
+ nsIWebProgressListener::STATE_SECURE_HIGH:
+ level = EPHY_EMBED_STATE_IS_SECURE_HIGH;
+ break;
+ case nsIWebProgressListener::STATE_IS_SECURE|
+ nsIWebProgressListener::STATE_SECURE_MED:
+ level = EPHY_EMBED_STATE_IS_SECURE_MED;
+ break;
+ case nsIWebProgressListener::STATE_IS_SECURE|
+ nsIWebProgressListener::STATE_SECURE_LOW:
+ level = EPHY_EMBED_STATE_IS_SECURE_LOW;
+ break;
+ default:
+ level = EPHY_EMBED_STATE_IS_UNKNOWN;
+ break;
+ }
+ return level;
+}
+
+static void
+ephy_embed_iface_init (EphyEmbedIface *iface)
+{
+ iface->load_url = impl_load_url;
+ iface->load = impl_load;
+ iface->stop_load = impl_stop_load;
+ iface->can_go_back = impl_can_go_back;
+ iface->can_go_forward =impl_can_go_forward;
+ iface->can_go_up = impl_can_go_up;
+ iface->get_go_up_list = impl_get_go_up_list;
+ iface->go_back = impl_go_back;
+ iface->go_forward = impl_go_forward;
+ iface->go_up = impl_go_up;
+ iface->get_title = impl_get_title;
+ iface->get_location = impl_get_location;
+ iface->get_link_message = impl_get_link_message;
+ iface->get_js_status = impl_get_js_status;
+ iface->reload = impl_reload;
+ iface->set_zoom = impl_set_zoom;
+ iface->get_zoom = impl_get_zoom;
+ iface->scroll_lines = impl_scroll_lines;
+ iface->scroll_pages = impl_scroll_pages;
+ iface->scroll_pixels = impl_scroll_pixels;
+ iface->shistory_n_items = impl_shistory_n_items;
+ iface->shistory_get_nth = impl_shistory_get_nth;
+ iface->shistory_get_pos = impl_shistory_get_pos;
+ iface->shistory_go_nth = impl_shistory_go_nth;
+ iface->shistory_copy = impl_shistory_copy;
+ iface->get_security_level = impl_get_security_level;
+ iface->show_page_certificate = impl_show_page_certificate;
+ iface->close = impl_close;
+ iface->set_encoding = impl_set_encoding;
+ iface->get_encoding = impl_get_encoding;
+ iface->has_automatic_encoding = impl_has_automatic_encoding;
+ iface->print = impl_print;
+ iface->set_print_preview_mode = impl_set_print_preview_mode;
+ iface->print_preview_n_pages = impl_print_preview_n_pages;
+ iface->print_preview_navigate = impl_print_preview_navigate;
+ iface->has_modified_forms = impl_has_modified_forms;
+}
+
+static void
+xul_visibility_cb (GtkWidget *embed, gboolean visibility, GtkWidget *window)
+{
+ if (visibility)
+ {
+ gtk_widget_show (window);
+ }
+ else
+ {
+ gtk_widget_hide (window);
+ }
+}
+
+static void
+xul_size_to_cb (GtkWidget *embed, gint width, gint height, gpointer dummy)
+{
+ gtk_widget_set_size_request (embed, width, height);
+}
+
+static void
+xul_new_window_cb (GeckoEmbed *embed,
+ GeckoEmbed **retval,
+ guint chrome_mask,
+ gpointer dummy)
+{
+ g_assert (chrome_mask & GECKO_EMBED_FLAG_OPENASCHROME);
+
+ *retval = _mozilla_embed_new_xul_dialog ();
+}
+
+static void
+xul_title_cb (GeckoEmbed *embed,
+ GtkWindow *window)
+{
+ char *title;
+
+ title = gecko_embed_get_title (embed);
+ gtk_window_set_title (window, title);
+ g_free (title);
+}
+
+GeckoEmbed *
+_mozilla_embed_new_xul_dialog (void)
+{
+ GtkWidget *window, *embed;
+
+ g_object_ref (embed_shell);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_object_set_data_full (G_OBJECT (window), "EmbedShellRef",
+ embed_shell,
+ (GDestroyNotify) g_object_unref);
+ g_signal_connect_object (embed_shell, "prepare_close",
+ G_CALLBACK (gtk_widget_destroy), window,
+ (GConnectFlags) G_CONNECT_SWAPPED);
+
+ embed = gecko_embed_new ();
+ gtk_widget_show (embed);
+ gtk_container_add (GTK_CONTAINER (window), embed);
+
+ g_signal_connect_object (embed, "destroy_browser",
+ G_CALLBACK (gtk_widget_destroy),
+ window, G_CONNECT_SWAPPED);
+ g_signal_connect_object (embed, "visibility",
+ G_CALLBACK (xul_visibility_cb),
+ window, (GConnectFlags) 0);
+ g_signal_connect_object (embed, "size_to",
+ G_CALLBACK (xul_size_to_cb),
+ NULL, (GConnectFlags) 0);
+ g_signal_connect_object (embed, "new_window",
+ G_CALLBACK (xul_new_window_cb),
+ NULL, (GConnectFlags) 0);
+ g_signal_connect_object (embed, "title",
+ G_CALLBACK (xul_title_cb),
+ window, (GConnectFlags) 0);
+
+ return GECKO_EMBED (embed);
+}
diff --git a/embed/xulrunner/embed/mozilla-embed.h b/embed/xulrunner/embed/mozilla-embed.h
new file mode 100644
index 000000000..be03cd6c3
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-embed.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2000-2004 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef MOZILLA_EMBED_H
+#define MOZILLA_EMBED_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "gecko-embed.h"
+#include "gecko-embed-types.h"
+
+#include "ephy-embed.h"
+
+G_BEGIN_DECLS
+
+#define MOZILLA_TYPE_EMBED (mozilla_embed_get_type ())
+#define MOZILLA_EMBED(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MOZILLA_TYPE_EMBED, MozillaEmbed))
+#define MOZILLA_EMBED_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MOZILLA_TYPE_EMBED, MozillaEmbedClass))
+#define MOZILLA_IS_EMBED(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MOZILLA_TYPE_EMBED))
+#define MOZILLA_IS_EMBED_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MOZILLA_TYPE_EMBED))
+#define MOZILLA_EMBED_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MOZILLA_TYPE_EMBED, MozillaEmbedClass))
+
+typedef struct MozillaEmbed MozillaEmbed;
+typedef struct MozillaEmbedPrivate MozillaEmbedPrivate;
+
+struct MozillaEmbed
+{
+ GeckoEmbed parent_instance;
+
+ /*< private >*/
+ MozillaEmbedPrivate *priv;
+};
+
+typedef GeckoEmbedClass MozillaEmbedClass;
+
+GType mozilla_embed_get_type (void);
+
+/* The following are private to the embed implementation */
+
+gpointer _mozilla_embed_get_ephy_browser (MozillaEmbed *embed);
+
+GeckoEmbed *_mozilla_embed_new_xul_dialog (void);
+
+EphyEmbedChrome _mozilla_embed_translate_chrome (GeckoEmbedChromeFlags flags);
+
+G_END_DECLS
+
+#endif
diff --git a/embed/xulrunner/embed/mozilla-notifiers.cpp b/embed/xulrunner/embed/mozilla-notifiers.cpp
new file mode 100644
index 000000000..9901bdbe2
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-notifiers.cpp
@@ -0,0 +1,1257 @@
+/*
+* Copyright © 2000 Nate Case
+* Copyright © 2000-2004 Marco Pesenti Gritti
+* Copyright © 2003, 2004 Christian Persch
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2, OR (AT YOUR OPTION)
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* $Id$
+*/
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtksettings.h>
+
+#include <nsCOMPtr.h>
+#include <nsIPrefService.h>
+#include <nsIServiceManager.h>
+#include <nsMemory.h>
+#include <nsServiceManagerUtils.h>
+
+#include "eel-gconf-extensions.h"
+#include "ephy-debug.h"
+#include "ephy-embed-prefs.h"
+#include "ephy-embed-shell.h"
+#include "ephy-encodings.h"
+#include "ephy-langs.h"
+#include "ephy-node.h"
+#include "ephy-prefs.h"
+
+#include "mozilla-notifiers.h"
+
+/* define to migrate epiphany 1.0 font preferences */
+#define MIGRATE_PIXEL_SIZE
+
+#define MAX_FONT_SIZE 128
+
+/* Keeps the list of the notifiers we installed for mozilla prefs */
+/* to be able to remove them when exiting */
+static GList *notifiers = NULL;
+static nsIPrefBranch *gPrefBranch;
+
+typedef struct
+{
+ char *gconf_key;
+ char *mozilla_pref;
+ PrefValueTransformFunc func;
+ gpointer user_data;
+ guint cnxn_id;
+} PrefData;
+
+static void
+free_pref_data (PrefData *data)
+{
+ g_free (data->gconf_key);
+ g_free (data->mozilla_pref);
+
+ g_slice_free (PrefData, data);
+}
+
+static gboolean
+transform_accept_languages_list (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ GConfValue *gcvalue;
+ GArray *array;
+ GSList *languages, *l;
+ char **langs;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_LIST ||
+ gconf_value_get_list_type (gcvalue) != GCONF_VALUE_STRING) return FALSE;
+
+ languages = gconf_value_get_list (gcvalue);
+
+ array = g_array_new (TRUE, FALSE, sizeof (char *));
+
+ for (l = languages; l != NULL; l = l->next)
+ {
+ const char *lang;
+
+ lang = gconf_value_get_string ((GConfValue *) l->data);
+
+ if (lang != NULL && strcmp (lang, "system") == 0)
+ {
+ ephy_langs_append_languages (array);
+ }
+ else if (lang != NULL && lang[0] != '\0')
+ {
+ char *str;
+ str = g_ascii_strdown (lang, -1);
+ g_array_append_val (array, str);
+ }
+ }
+
+ ephy_langs_sanitise (array);
+
+ langs = (char **) g_array_free (array, FALSE);
+
+ g_value_init (value, G_TYPE_STRING);
+ g_value_take_string (value, g_strjoinv (",", langs));
+
+ g_strfreev (langs);
+
+ return TRUE;
+}
+
+static gboolean
+transform_cache_size (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ GConfValue *gcvalue;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_INT) return FALSE;
+
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, gconf_value_get_int (gcvalue) * 1024);
+
+ return TRUE;
+}
+
+static gboolean
+transform_cookies_accept_mode (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+
+{
+ GConfValue *gcvalue;
+ const char *mode;
+ int mozilla_mode = 0;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_STRING) return FALSE;
+
+ mode = gconf_value_get_string (gcvalue);
+ if (mode == NULL) return FALSE;
+
+ if (strcmp (mode, "anywhere") == 0)
+ {
+ mozilla_mode = 0;
+ }
+ else if (strcmp (mode, "current site") == 0)
+ {
+ mozilla_mode = 1;
+ }
+ else if (strcmp (mode, "nowhere") == 0)
+ {
+ mozilla_mode = 2;
+ }
+
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, mozilla_mode);
+
+ return TRUE;
+}
+
+static gboolean
+transform_encoding (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ GConfValue *gcvalue;
+ EphyEncodings *encodings;
+ EphyNode *node;
+ const char *code;
+ gboolean is_autodetector;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_STRING) return FALSE;
+
+ code = gconf_value_get_string (gcvalue);
+ if (code == NULL) return FALSE;
+
+ encodings = EPHY_ENCODINGS (ephy_embed_shell_get_encodings (embed_shell));
+ node = ephy_encodings_get_node (encodings, code, FALSE);
+ if (node == NULL) return FALSE;
+
+ is_autodetector = ephy_node_get_property_boolean (node, EPHY_NODE_ENCODING_PROP_IS_AUTODETECTOR);
+ if (is_autodetector != GPOINTER_TO_INT (user_data)) return FALSE;
+
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, code);
+
+ return TRUE;
+}
+
+static gboolean
+transform_image_animation_mode (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+
+{
+ GConfValue *gcvalue;
+ const char *mode;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_STRING) return FALSE;
+
+ mode = gconf_value_get_string (gcvalue);
+ if (mode == NULL) return FALSE;
+
+ if (strcmp (mode, "disabled") == 0)
+ {
+ mode = "none";
+ }
+
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, mode);
+
+ return TRUE;
+}
+
+static gboolean
+transform_proxy_ignore_list (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ GConfValue *gcvalue;
+ GArray *array;
+ GSList *hosts, *l;
+ char **strings;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_LIST ||
+ gconf_value_get_list_type (gcvalue) != GCONF_VALUE_STRING) return FALSE;
+
+ hosts = gconf_value_get_list (gcvalue);
+
+ array = g_array_new (TRUE, FALSE, sizeof (char *));
+
+ for (l = hosts; l != NULL; l = l->next)
+ {
+ const char *host;
+
+ host = gconf_value_get_string ((GConfValue *) l->data);
+
+ if (host != NULL && host[0] != '\0')
+ {
+ g_array_append_val (array, host);
+ }
+ }
+
+ strings = (char **) g_array_free (array, FALSE);
+
+ g_value_init (value, G_TYPE_STRING);
+ g_value_take_string (value, g_strjoinv (",", strings));
+
+ /* the strings themselves are const */
+ g_free (strings);
+
+ return TRUE;
+}
+
+static gboolean
+transform_proxy_mode (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ GConfValue *gcvalue;
+ const char *mode;
+ int mozilla_mode = 0;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_STRING) return FALSE;
+
+ mode = gconf_value_get_string (gcvalue);
+ if (mode == NULL) return FALSE;
+
+ if (strcmp (mode, "manual") == 0)
+ {
+ mozilla_mode = 1;
+ }
+ else if (strcmp (mode, "auto") == 0)
+ {
+ mozilla_mode = 2;
+ }
+
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, mozilla_mode);
+
+ return TRUE;
+}
+
+static gboolean
+transform_use_own_fonts (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ GConfValue *gcvalue;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_BOOL) return FALSE;
+
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, gconf_value_get_bool (gcvalue) ? 0 : 1);
+
+ return TRUE;
+}
+
+extern "C" gboolean
+mozilla_notifier_transform_bool (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ GConfValue *gcvalue;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_BOOL) return FALSE;
+
+ g_value_init (value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (value, gconf_value_get_bool (gcvalue));
+
+ return TRUE;
+}
+
+extern "C" gboolean
+mozilla_notifier_transform_bool_invert (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ GConfValue *gcvalue;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_BOOL) return FALSE;
+
+ g_value_init (value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (value, !gconf_value_get_bool (gcvalue));
+
+ return TRUE;
+}
+
+extern "C" gboolean
+mozilla_notifier_transform_int (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ GConfValue *gcvalue;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_INT) return FALSE;
+
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, gconf_value_get_int (gcvalue));
+
+ return TRUE;
+}
+
+extern "C" gboolean
+mozilla_notifier_transform_string (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ GConfValue *gcvalue;
+ const char *str;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_STRING) return FALSE;
+
+ str = gconf_value_get_string (gcvalue);
+ if (str == NULL) return FALSE;
+
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, str);
+
+ return TRUE;
+}
+
+static const PrefData notifier_entries[] =
+{
+ { CONF_BROWSE_WITH_CARET,
+ "accessibility.browsewithcaret",
+ mozilla_notifier_transform_bool },
+ { CONF_NETWORK_CACHE_SIZE,
+ "browser.cache.disk.capacity",
+ transform_cache_size },
+ { CONF_RENDERING_USE_OWN_COLORS,
+ "browser.display.use_document_colors",
+ mozilla_notifier_transform_bool_invert },
+ { CONF_RENDERING_USE_OWN_FONTS,
+ "browser.display.use_document_fonts",
+ transform_use_own_fonts },
+ { CONF_SECURITY_ALLOW_POPUPS,
+ "dom.disable_open_during_load",
+ mozilla_notifier_transform_bool_invert },
+ { CONF_DISPLAY_SMOOTHSCROLL,
+ "general.smoothScroll",
+ mozilla_notifier_transform_bool },
+ { CONF_IMAGE_ANIMATION_MODE,
+ "image.animation_mode",
+ transform_image_animation_mode },
+ { CONF_RENDERING_LANGUAGE,
+ "intl.accept_languages",
+ transform_accept_languages_list },
+ { CONF_LANGUAGE_DEFAULT_ENCODING,
+ "intl.charset.default",
+ transform_encoding,
+ GINT_TO_POINTER (FALSE) },
+ { CONF_LANGUAGE_AUTODETECT_ENCODING,
+ "intl.charset.detector",
+ transform_encoding,
+ GINT_TO_POINTER (TRUE) },
+ { CONF_SECURITY_JAVA_ENABLED,
+ "security.enable_java",
+ mozilla_notifier_transform_bool },
+ { CONF_SECURITY_JAVASCRIPT_ENABLED,
+ "javascript.enabled",
+ mozilla_notifier_transform_bool },
+ { CONF_NETWORK_PROXY_AUTO_URL,
+ "network.proxy.autoconfig_url",
+ mozilla_notifier_transform_string },
+ { CONF_NETWORK_HTTP_PROXY,
+ "network.proxy.http",
+ mozilla_notifier_transform_string },
+ { CONF_NETWORK_HTTP_PROXY_PORT,
+ "network.proxy.http_port",
+ mozilla_notifier_transform_int },
+ { CONF_NETWORK_FTP_PROXY,
+ "network.proxy.ftp",
+ mozilla_notifier_transform_string },
+ { CONF_NETWORK_FTP_PROXY_PORT,
+ "network.proxy.ftp_port",
+ mozilla_notifier_transform_int },
+ { CONF_NETWORK_SSL_PROXY,
+ "network.proxy.ssl",
+ mozilla_notifier_transform_string },
+ { CONF_NETWORK_SSL_PROXY_PORT,
+ "network.proxy.ssl_port",
+ mozilla_notifier_transform_int },
+ { CONF_NETWORK_SOCKS_PROXY,
+ "network.proxy.socks",
+ mozilla_notifier_transform_string },
+ { CONF_NETWORK_SOCKS_PROXY_PORT,
+ "network.proxy.socks_port",
+ mozilla_notifier_transform_int },
+ { CONF_NETWORK_PROXY_IGNORE_HOSTS,
+ "network.proxy.no_proxies_on",
+ transform_proxy_ignore_list },
+ { CONF_NETWORK_PROXY_MODE,
+ "network.proxy.type",
+ transform_proxy_mode },
+ { CONF_SECURITY_COOKIES_ACCEPT,
+ "network.cookie.cookieBehavior",
+ transform_cookies_accept_mode },
+ { CONF_PRIVACY_REMEMBER_PASSWORDS,
+ "signon.rememberSignons",
+ mozilla_notifier_transform_bool }
+};
+
+gboolean
+mozilla_pref_set (const char *pref,
+ const GValue *value)
+{
+ NS_ENSURE_TRUE (gPrefBranch, FALSE);
+
+ g_return_val_if_fail (pref != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ nsresult rv;
+ PRInt32 prefType;
+ rv = gPrefBranch->GetPrefType (pref, &prefType);
+ if (NS_FAILED (rv))
+ {
+ /* probably just an unset pref */
+ prefType = nsIPrefBranch::PREF_INVALID;
+ rv = NS_OK;
+ }
+
+ switch (G_VALUE_TYPE (value))
+ {
+ case G_TYPE_INT:
+ {
+ if (prefType != nsIPrefBranch::PREF_INT &&
+ prefType != nsIPrefBranch::PREF_INVALID)
+ break;
+
+ PRInt32 old_value = 0;
+ PRInt32 new_value = g_value_get_int (value);
+ rv = gPrefBranch->GetIntPref (pref, &old_value);
+ if (NS_FAILED (rv) || old_value != new_value)
+ {
+ rv = gPrefBranch->SetIntPref (pref, new_value);
+ }
+ break;
+ }
+ case G_TYPE_BOOLEAN:
+ {
+ if (prefType != nsIPrefBranch::PREF_BOOL &&
+ prefType != nsIPrefBranch::PREF_INVALID)
+ break;
+
+ PRBool old_value = PR_FALSE;
+ PRBool new_value = g_value_get_boolean (value);
+ rv = gPrefBranch->GetBoolPref (pref, &old_value);
+ if (NS_FAILED (rv) || old_value != new_value)
+ {
+ rv = gPrefBranch->SetBoolPref (pref, new_value);
+ }
+ break;
+ }
+ case G_TYPE_STRING:
+ {
+ if (prefType != nsIPrefBranch::PREF_STRING &&
+ prefType != nsIPrefBranch::PREF_INVALID)
+ break;
+
+ const char *new_value = g_value_get_string (value);
+ if (new_value == NULL)
+ {
+ rv = gPrefBranch->ClearUserPref (pref);
+ }
+ else
+ {
+ char *old_value = nsnull;
+
+ rv = gPrefBranch->GetCharPref (pref, &old_value);
+ if (NS_FAILED (rv) ||
+ old_value == nsnull ||
+ strcmp (old_value, new_value) != 0)
+ {
+ rv = gPrefBranch->SetCharPref (pref, new_value);
+ }
+
+ if (old_value)
+ {
+ nsMemory::Free (old_value);
+ }
+ }
+ break;
+ }
+ default:
+ g_return_val_if_reached (FALSE);
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+
+ return NS_SUCCEEDED (rv) != PR_FALSE;
+}
+
+static void
+notify_cb (GConfClient *client,
+ guint cnxn_id,
+ GConfEntry *gcentry,
+ PrefData *data)
+{
+ GValue value = { 0, };
+
+ g_return_if_fail (gcentry != NULL);
+ g_assert (data != NULL);
+
+ if (data->func (gcentry, &value, data->user_data))
+ {
+ mozilla_pref_set (data->mozilla_pref, &value);
+ g_value_unset (&value);
+ }
+ else
+ {
+ /* Reset the pref */
+ NS_ENSURE_TRUE (gPrefBranch, );
+ gPrefBranch->ClearUserPref (data->mozilla_pref);
+ }
+}
+
+extern "C" guint
+mozilla_notifier_add (const char *gconf_key,
+ const char *mozilla_pref,
+ PrefValueTransformFunc func,
+ gpointer user_data)
+{
+ GConfClient *client;
+ PrefData *data;
+ GError *error = NULL;
+ guint cnxn_id;
+
+ g_return_val_if_fail (gconf_key != NULL, 0);
+ g_return_val_if_fail (mozilla_pref != NULL, 0);
+ g_return_val_if_fail (func, 0);
+
+ client = eel_gconf_client_get_global ();
+ g_return_val_if_fail (client != NULL, 0);
+
+ data = g_slice_new (PrefData);
+ data->gconf_key = g_strdup (gconf_key);
+ data->mozilla_pref = g_strdup (mozilla_pref);
+ data->func = func;
+ data->user_data = user_data;
+
+ cnxn_id = gconf_client_notify_add (client, gconf_key,
+ (GConfClientNotifyFunc) notify_cb,
+ data, (GFreeFunc) free_pref_data,
+ &error);
+ if (eel_gconf_handle_error (&error))
+ {
+ if (cnxn_id != EEL_GCONF_UNDEFINED_CONNECTION)
+ {
+ gconf_client_notify_remove (client, cnxn_id);
+ }
+
+ return 0;
+ }
+
+ data->cnxn_id = cnxn_id;
+ notifiers = g_list_prepend (notifiers, data);
+
+ gconf_client_notify (client, gconf_key);
+
+ return cnxn_id;
+}
+
+static int
+find_data (const PrefData *a,
+ gconstpointer idptr)
+{
+ return a->cnxn_id != GPOINTER_TO_UINT (idptr);
+}
+
+extern "C" void
+mozilla_notifier_remove (guint id)
+{
+ GList *l;
+
+ g_return_if_fail (id != 0);
+
+ l = g_list_find_custom (notifiers, GUINT_TO_POINTER (id),
+ (GCompareFunc) find_data);
+ g_return_if_fail (l != NULL);
+
+ notifiers = g_list_delete_link (notifiers, l);
+ eel_gconf_notification_remove (id);
+}
+
+#ifdef MIGRATE_PIXEL_SIZE
+
+#define INT_ROUND(a) gint((a) + 0.5f)
+
+/**
+* This function gets the dpi in the same way that mozilla gets the dpi,
+* this allows us to convert from pixels to points easily
+*/
+static gint
+mozilla_get_dpi ()
+{
+ GtkSettings* settings = gtk_settings_get_default ();
+ gint dpi = 0;
+
+ /* Use the gdk-xft-dpi setting if it is set */
+ if (g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (settings)),
+ "gtk-xft-dpi"))
+ {
+ g_object_get (G_OBJECT (settings), "gtk-xft-dpi", &dpi, (char *) NULL);
+ if (dpi) return INT_ROUND (dpi / PANGO_SCALE);
+ }
+
+ /* Fall back to what xft thinks it is */
+ char *val = XGetDefault (GDK_DISPLAY (), "Xft", "dpi");
+ if (val)
+ {
+ char *e;
+ double d = strtod(val, &e);
+ if (e != val) return INT_ROUND (d);
+ }
+
+ /* Fall back to calculating manually from the gdk screen settings */
+ float screenWidthIn = float (gdk_screen_width_mm()) / 25.4f;
+ return INT_ROUND (gdk_screen_width() / screenWidthIn);
+}
+
+static void
+migrate_font_gconf_key (const char *pixel_key,
+ const char *point_key)
+{
+ int size;
+
+ size = eel_gconf_get_integer (pixel_key);
+
+ if (size > 0)
+ {
+ /* Use doubles to get more accurate arithmetic */
+ double dpi = (double) mozilla_get_dpi ();
+ double value = (double) eel_gconf_get_integer (pixel_key);
+ gint point = INT_ROUND ((value * 72) / dpi);
+
+ eel_gconf_set_integer (point_key, point);
+ }
+}
+
+#endif
+
+static gboolean
+parse_pango_font (const char *font,
+ char **name,
+ int *size)
+{
+ PangoFontMask mask = (PangoFontMask) (PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_SIZE);
+
+ PangoFontDescription *desc = pango_font_description_from_string (font);
+ if (desc == NULL) return FALSE;
+
+ if ((pango_font_description_get_set_fields (desc) & mask) != mask)
+ {
+ pango_font_description_free (desc);
+ return FALSE;
+ }
+
+ *size = PANGO_PIXELS (pango_font_description_get_size (desc));
+ *name = g_strdup (pango_font_description_get_family (desc));
+
+ pango_font_description_free (desc);
+
+ LOG ("Parsed pango font description '%s' -> name:%s, size:%d",
+ font, *name ? *name : "-", *size);
+
+ return *name != NULL && *size > 0;
+}
+
+typedef struct
+{
+ guint cnxn_id;
+ char **font_name_prefs;
+ char **font_size_prefs;
+ char *font_name;
+ int font_size;
+} DesktopFontData;
+
+static gboolean
+transform_font_name (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ DesktopFontData *data = (DesktopFontData *) user_data;
+ GConfValue *gcvalue;
+ const char *font_name;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gconf_entry_get_is_default (gcentry) ||
+ gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_STRING)
+ {
+ font_name = data->font_name;
+ }
+ else
+ {
+ font_name = gconf_value_get_string (gcvalue);
+ if ((font_name == NULL || font_name[0] == '\0'))
+ {
+ font_name = data->font_name;
+ }
+ }
+
+ LOG ("%s value for key '%s'",
+ gconf_entry_get_is_default (gcentry) ? "default" : "NON-default",
+ gconf_entry_get_key (gcentry));
+
+ if (font_name == NULL) return FALSE;
+
+ LOG ("Inferred font name '%s' for key '%s'",
+ font_name, gconf_entry_get_key (gcentry));
+
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, font_name);
+
+ return TRUE;
+}
+
+static gboolean
+transform_font_size (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ DesktopFontData *data = (DesktopFontData *) user_data;
+ GConfValue *gcvalue;
+ int size = 0;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gconf_entry_get_is_default (gcentry) ||
+ gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_INT)
+ {
+ size = data->font_size;
+ }
+ else
+ {
+ size = gconf_value_get_int (gcvalue);
+ }
+
+ if (size <= 0 || size > MAX_FONT_SIZE) return FALSE;
+
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, size);
+
+ return TRUE;
+}
+
+static void
+notify_desktop_font_cb (GConfClient *client,
+ guint cnxn_id,
+ GConfEntry *gcentry,
+ DesktopFontData *data)
+{
+ GConfValue *gcvalue;
+ char *name = NULL;
+ int size = 0, i;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue != NULL &&
+ gcvalue->type == GCONF_VALUE_STRING &&
+ parse_pango_font (gconf_value_get_string (gcvalue), &name, &size))
+ {
+ LOG ("Desktop font %s -> name=%s, size=%d",
+ gconf_entry_get_key (gcentry), name, size);
+
+ g_free (data->font_name);
+ data->font_name = name;
+ data->font_size = size;
+ }
+ else
+ {
+ g_free (name);
+
+ g_free (data->font_name);
+ data->font_name = NULL;
+ data->font_size = 0;
+ }
+
+ for (i = 0; data->font_name_prefs[i] != NULL; ++i)
+ {
+ gconf_client_notify (client, data->font_name_prefs[i]);
+ }
+ for (i = 0; data->font_size_prefs[i] != NULL; ++i)
+ {
+ gconf_client_notify (client, data->font_size_prefs[i]);
+ }
+}
+
+typedef struct
+{
+ guint cnxn_id;
+ char **prefs;
+ int size;
+} MinimumFontSizeData;
+
+static gboolean
+transform_minimum_font_size (GConfEntry *gcentry,
+ GValue *value,
+ gpointer user_data)
+{
+ MinimumFontSizeData *data = (MinimumFontSizeData *) user_data;
+ GConfValue *gcvalue;
+ int size = 0;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (gcvalue == NULL ||
+ gcvalue->type != GCONF_VALUE_INT)
+ {
+ size = data->size;
+ }
+ else
+ {
+ size = MAX (gconf_value_get_int (gcvalue),
+ data->size);
+ }
+
+ if (size <= 0) return FALSE;
+
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, size);
+
+ return TRUE;
+}
+
+static void
+notify_minimum_size_cb (GConfClient *client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ MinimumFontSizeData *data)
+{
+ GConfValue *gcvalue;
+ int i;
+
+ data->size = 0;
+
+ gcvalue = gconf_entry_get_value (entry);
+ /* happens on initial notify if the key doesn't exist */
+ if (gcvalue != NULL &&
+ gcvalue->type == GCONF_VALUE_INT)
+ {
+ data->size = gconf_value_get_int (gcvalue);
+ data->size = MAX (data->size, 0);
+ }
+
+ LOG ("Minimum font size now %d", data->size);
+
+ for (i = 0; data->prefs[i] != NULL; ++i)
+ {
+ gconf_client_notify (client, data->prefs[i]);
+ }
+}
+
+static DesktopFontData *desktop_font_data;
+static MinimumFontSizeData *minimum_font_size_data;
+
+static void
+mozilla_font_notifiers_init (void)
+{
+ static const char *types [] = { "variable", "monospace" };
+ const EphyFontsLanguageInfo *font_languages;
+ guint n_font_languages, i;
+
+ eel_gconf_monitor_add ("/desktop/gnome/interface");
+
+ font_languages = ephy_font_languages ();
+ n_font_languages = ephy_font_n_languages ();
+
+ desktop_font_data = g_new0 (DesktopFontData, 2);
+ desktop_font_data[0].font_name_prefs = g_new0 (char*, n_font_languages + 1);
+ desktop_font_data[0].font_size_prefs = g_new0 (char*, n_font_languages + 1);
+ desktop_font_data[1].font_name_prefs = g_new0 (char*, n_font_languages + 1);
+ desktop_font_data[1].font_size_prefs = g_new0 (char*, n_font_languages + 1);
+
+ desktop_font_data[0].cnxn_id =
+ eel_gconf_notification_add (CONF_DESKTOP_FONT_VARIABLE,
+ (GConfClientNotifyFunc) notify_desktop_font_cb,
+ &desktop_font_data[0]);
+ eel_gconf_notify (CONF_DESKTOP_FONT_VARIABLE);
+
+ desktop_font_data[1].cnxn_id =
+ eel_gconf_notification_add (CONF_DESKTOP_FONT_MONOSPACE,
+ (GConfClientNotifyFunc) notify_desktop_font_cb,
+ &desktop_font_data[1]);
+ eel_gconf_notify (CONF_DESKTOP_FONT_MONOSPACE);
+
+ minimum_font_size_data = g_new0 (MinimumFontSizeData, 1);
+ minimum_font_size_data->prefs = g_new0 (char*, n_font_languages + 1);
+
+ minimum_font_size_data->cnxn_id =
+ eel_gconf_notification_add (CONF_RENDERING_FONT_MIN_SIZE,
+ (GConfClientNotifyFunc) notify_minimum_size_cb,
+ minimum_font_size_data);
+ eel_gconf_notify (CONF_RENDERING_FONT_MIN_SIZE);
+
+#ifdef MIGRATE_PIXEL_SIZE
+ gboolean migrate_size;
+
+ migrate_size = (eel_gconf_get_integer (CONF_SCHEMA_VERSION)
+ < EPIPHANY_SCHEMA_VERSION);
+ if (migrate_size)
+ {
+ eel_gconf_set_integer (CONF_SCHEMA_VERSION, EPIPHANY_SCHEMA_VERSION);
+ }
+#endif
+
+ for (i=0; i < n_font_languages; i++)
+ {
+ const char *code = font_languages[i].code;
+ guint k;
+ char key[255], pref[255];
+#ifdef MIGRATE_PIXEL_SIZE
+ char old_key[255];
+#endif
+
+ for (k = 0; k < G_N_ELEMENTS (types); k++)
+ {
+ g_snprintf (key, sizeof (key), "%s_%s_%s",
+ CONF_RENDERING_FONT, types[k], code);
+ g_snprintf (pref, sizeof (pref), "font.name.%s.%s",
+ types[k], code);
+
+ desktop_font_data[k].font_name_prefs[i] = g_strdup (key);
+
+ mozilla_notifier_add (key, pref,
+ transform_font_name,
+ &desktop_font_data[k]);
+ }
+
+#ifdef MIGRATE_PIXEL_SIZE
+ if (migrate_size)
+ {
+ char *type;
+
+ type = eel_gconf_get_string (CONF_RENDERING_FONT_TYPE_OLD);
+ if (type && (strcmp (type, "serif") == 0 ||
+ strcmp (type, "sans-serif") == 0))
+ {
+ char *family;
+
+ g_snprintf (old_key, sizeof (old_key), "%s_%s_%s",
+ CONF_RENDERING_FONT, type, code);
+ g_snprintf (key, sizeof (key), "%s_%s_%s",
+ CONF_RENDERING_FONT, "variable", code);
+
+ family = eel_gconf_get_string (old_key);
+ if (family)
+ {
+ eel_gconf_set_string (key, family);
+ g_free (family);
+ }
+ }
+
+ g_free (type);
+ }
+#endif
+
+ /* FIXME is it "minimum-size" or "min-size" !!? */
+ g_snprintf (key, sizeof (key), "%s_%s",
+ CONF_RENDERING_FONT_MIN_SIZE, code);
+ g_snprintf (pref, sizeof (pref), "font.minimum-size.%s", code);
+
+ minimum_font_size_data->prefs[i] = g_strdup (key);
+
+ mozilla_notifier_add (key, pref, transform_minimum_font_size,
+ minimum_font_size_data);
+
+#ifdef MIGRATE_PIXEL_SIZE
+ if (migrate_size)
+ {
+ g_snprintf (old_key, sizeof (key), "%s_%s",
+ CONF_RENDERING_FONT_MIN_SIZE_OLD, code);
+ migrate_font_gconf_key (old_key, key);
+ }
+#endif
+
+ g_snprintf (key, sizeof (key), "%s_%s",
+ CONF_RENDERING_FONT_FIXED_SIZE, code);
+ g_snprintf (pref, sizeof (pref), "font.size.fixed.%s", code);
+
+ desktop_font_data[1].font_size_prefs[i] = g_strdup (key);
+ mozilla_notifier_add (key, pref, transform_font_size,
+ &desktop_font_data[1]);
+
+#ifdef MIGRATE_PIXEL_SIZE
+ if (migrate_size)
+ {
+ g_snprintf (old_key, sizeof (old_key), "%s_%s",
+ CONF_RENDERING_FONT_FIXED_SIZE_OLD, code);
+ migrate_font_gconf_key (old_key, key);
+ }
+#endif
+
+ g_snprintf (key, sizeof (key), "%s_%s",
+ CONF_RENDERING_FONT_VAR_SIZE, code);
+ g_snprintf (pref, sizeof (pref), "font.size.variable.%s", code);
+
+ desktop_font_data[0].font_size_prefs[i] = g_strdup (key);
+ mozilla_notifier_add (key, pref, transform_font_size,
+ &desktop_font_data[0]);
+
+#ifdef MIGRATE_PIXEL_SIZE
+ if (migrate_size)
+ {
+ g_snprintf (old_key, sizeof (old_key), "%s_%s",
+ CONF_RENDERING_FONT_VAR_SIZE_OLD, code);
+ migrate_font_gconf_key (old_key, key);
+ }
+#endif
+ }
+}
+
+static void
+mozilla_font_notifiers_shutdown (void)
+{
+ eel_gconf_monitor_remove ("/desktop/gnome/interface");
+
+ eel_gconf_notification_remove (desktop_font_data[0].cnxn_id);
+ eel_gconf_notification_remove (desktop_font_data[1].cnxn_id);
+ eel_gconf_notification_remove (minimum_font_size_data->cnxn_id);
+
+ g_free (desktop_font_data[0].font_name);
+ g_free (desktop_font_data[1].font_name);
+
+ g_strfreev (desktop_font_data[0].font_name_prefs);
+ g_strfreev (desktop_font_data[0].font_size_prefs);
+ g_strfreev (desktop_font_data[1].font_name_prefs);
+ g_strfreev (desktop_font_data[1].font_size_prefs);
+ g_strfreev (minimum_font_size_data->prefs);
+
+ g_free (desktop_font_data);
+ g_free (minimum_font_size_data);
+}
+
+#if 0
+static void
+notify_generic_cb (GConfClient *client,
+ guint cnxn_id,
+ GConfEntry *gcentry,
+ gpointer data)
+{
+ GConfValue *gcvalue;
+ const char *key, *pref;
+ static const gsize len = strlen ("/apps/epiphany/web/gecko_prefs/");
+ GValue value = { 0, };
+
+ key = gconf_entry_get_key (gcentry);
+ if (!key || strlen (key) <= len) return;
+
+ pref = key + len;
+
+ gcvalue = gconf_entry_get_value (gcentry);
+ if (!gcvalue) return;
+
+ switch (gcvalue->type)
+ {
+ case GCONF_VALUE_STRING:
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_static_string (&value, gconf_value_get_string (gcvalue));
+ break;
+ case GCONF_VALUE_INT:
+ g_value_init (&value, G_TYPE_INT);
+ g_value_set_int (&value, gconf_value_get_int (gcvalue));
+ break;
+ case GCONF_VALUE_BOOL:
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&value, gconf_value_get_bool (gcvalue));
+ break;
+ /* case GCONF_VALUE_INVALID: */
+ /* case GCONF_VALUE_FLOAT: */
+ /* case GCONF_VALUE_SCHEMA: */
+ /* case GCONF_VALUE_LIST: */
+ /* case GCONF_VALUE_PAIR: */
+ default:
+ g_warning ("Unsupported value type for key '%s'\n", key);
+ return;
+ }
+
+ g_assert (G_IS_VALUE (&value));
+ mozilla_pref_set (pref, &value);
+ g_value_unset (&value);
+}
+
+static void
+mozilla_generic_notifier_init (void)
+{
+ GConfClient *client;
+ GError *error = NULL;
+ guint cnxn_id;
+ PrefData *data;
+ GSList *list, *l;
+
+ client = eel_gconf_client_get_global ();
+
+ cnxn_id = gconf_client_notify_add (client, "/apps/epiphany/web/gecko_prefs",
+ (GConfClientNotifyFunc) notify_generic_cb,
+ NULL, NULL, &error);
+ if (eel_gconf_handle_error (&error))
+ {
+ if (cnxn_id != EEL_GCONF_UNDEFINED_CONNECTION)
+ {
+ gconf_client_notify_remove (client, cnxn_id);
+ }
+
+ return;
+ }
+
+ data = g_slice_new0 (PrefData);
+ data->cnxn_id = cnxn_id;
+ notifiers = g_list_prepend (notifiers, data);
+
+ list = gconf_client_all_entries (client, "/apps/epiphany/web/gecko_prefs", NULL);
+ for (l = list; l != NULL; l = l->next)
+ {
+ GConfEntry *gcentry = (GConfEntry *) l->data;
+
+ notify_generic_cb (client, cnxn_id, gcentry, NULL);
+ gconf_entry_unref (gcentry);
+ }
+ g_slist_free (list);
+}
+#endif
+
+extern "C" gboolean
+mozilla_notifiers_init (void)
+{
+ guint i;
+
+ eel_gconf_monitor_add ("/apps/epiphany/web");
+ eel_gconf_monitor_add ("/system/proxy");
+ eel_gconf_monitor_add ("/system/http_proxy");
+
+ /* the pref service conveniently implements the root pref branch */
+ gPrefBranch = nsnull;
+ nsresult rv = CallGetService (NS_PREFSERVICE_CONTRACTID, &gPrefBranch);
+ if (NS_FAILED (rv) || !gPrefBranch)
+ {
+ g_warning ("Failed to get the pref service!\n");
+ return FALSE;
+ }
+
+#if 0
+ /* First init the generic notifier, so our regular prefs override prefs set there */
+ mozilla_generic_notifier_init ();
+#endif
+
+ for (i = 0; i < G_N_ELEMENTS (notifier_entries); i++)
+ {
+ mozilla_notifier_add (notifier_entries[i].gconf_key,
+ notifier_entries[i].mozilla_pref,
+ notifier_entries[i].func,
+ notifier_entries[i].user_data);
+ }
+
+ mozilla_font_notifiers_init ();
+
+ return TRUE;
+}
+
+static void
+remove_notification (PrefData *data)
+{
+ eel_gconf_notification_remove (data->cnxn_id);
+}
+
+extern "C" void
+mozilla_notifiers_shutdown (void)
+{
+ NS_IF_RELEASE (gPrefBranch);
+ gPrefBranch = nsnull;
+
+ mozilla_font_notifiers_shutdown ();
+
+ eel_gconf_monitor_remove ("/apps/epiphany/web");
+ eel_gconf_monitor_remove ("/system/proxy");
+ eel_gconf_monitor_remove ("/system/http_proxy");
+
+ g_list_foreach (notifiers, (GFunc) remove_notification, NULL);
+ g_list_free (notifiers);
+}
diff --git a/embed/xulrunner/embed/mozilla-notifiers.h b/embed/xulrunner/embed/mozilla-notifiers.h
new file mode 100644
index 000000000..d1fe6d7aa
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-notifiers.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2000 Nate Case
+ * Copyright © 2000-2004 Marco Pesenti Gritti
+ * Copyright © 2003, 2004 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef MOZILLA_NOTIFIERS_H
+#define MOZILLA_NOTIFIERS_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gconf/gconf.h>
+
+G_BEGIN_DECLS
+
+typedef gboolean (* PrefValueTransformFunc) (GConfEntry*, GValue*, gpointer);
+
+gboolean mozilla_notifier_transform_bool (GConfEntry*, GValue*, gpointer);
+
+gboolean mozilla_notifier_transform_bool_invert (GConfEntry*, GValue*, gpointer);
+
+gboolean mozilla_notifier_transform_int (GConfEntry*, GValue*, gpointer);
+
+gboolean mozilla_notifier_transform_string (GConfEntry*, GValue*, gpointer);
+
+guint mozilla_notifier_add (const char *gconf_key,
+ const char *mozilla_pref,
+ PrefValueTransformFunc func,
+ gpointer user_data);
+
+void mozilla_notifier_remove (guint id);
+
+gboolean mozilla_pref_set (const char *pref,
+ const GValue *value);
+
+gboolean mozilla_notifiers_init (void);
+
+void mozilla_notifiers_shutdown (void);
+
+G_END_DECLS
+
+#endif
diff --git a/embed/xulrunner/embed/mozilla-x509-cert.cpp b/embed/xulrunner/embed/mozilla-x509-cert.cpp
new file mode 100644
index 000000000..8774425cd
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-x509-cert.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright © 2003 Robert Marcano
+ * Copyright © 2005 Crispin Flowerday
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+#include "config.h"
+
+#include <nsStringAPI.h>
+
+#include "ephy-debug.h"
+
+#include "mozilla-x509-cert.h"
+
+#define MOZILLA_X509_CERT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
+ MOZILLA_TYPE_X509_CERT, MozillaX509CertPrivate))
+
+static void mozilla_x509_cert_class_init (MozillaX509CertClass *klass);
+static void ephy_x509_cert_init (EphyX509CertIface *iface);
+static void mozilla_x509_cert_init (MozillaX509Cert *cert);
+
+struct _MozillaX509CertPrivate
+{
+ nsIX509Cert * mozilla_cert;
+ gchar *title;
+};
+
+enum
+{
+ PROP_0,
+ PROP_MOZILLA_CERT
+};
+
+static GObjectClass *parent_class = NULL;
+
+GType
+mozilla_x509_cert_get_type (void)
+{
+ static GType mozilla_x509_cert_type = 0;
+
+ if (mozilla_x509_cert_type == 0)
+ {
+ const GTypeInfo our_info =
+ {
+ sizeof (MozillaX509CertClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) mozilla_x509_cert_class_init,
+ NULL,
+ NULL, /* class_data */
+ sizeof (MozillaX509Cert),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mozilla_x509_cert_init
+ };
+
+ const GInterfaceInfo x509_cert_info =
+ {
+ (GInterfaceInitFunc) ephy_x509_cert_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ };
+
+ mozilla_x509_cert_type = g_type_register_static (G_TYPE_OBJECT,
+ "MozillaX509Cert",
+ &our_info,
+ (GTypeFlags)0);
+ g_type_add_interface_static (mozilla_x509_cert_type,
+ EPHY_TYPE_X509_CERT,
+ &x509_cert_info);
+ }
+
+ return mozilla_x509_cert_type;
+}
+
+static void
+mozilla_x509_cert_set_mozilla_cert (MozillaX509Cert *cert,
+ nsIX509Cert *mozilla_cert)
+{
+ nsCOMPtr<nsIX509Cert> tmpcert = cert->priv->mozilla_cert;
+
+ if (cert->priv->mozilla_cert)
+ {
+ NS_RELEASE (cert->priv->mozilla_cert);
+ }
+
+ cert->priv->mozilla_cert = mozilla_cert;
+ NS_IF_ADDREF (cert->priv->mozilla_cert);
+}
+
+
+nsresult
+mozilla_x509_cert_get_mozilla_cert (MozillaX509Cert *cert, nsIX509Cert**aCert)
+{
+ *aCert = cert->priv->mozilla_cert;
+ NS_IF_ADDREF (*aCert);
+
+ return *aCert ? NS_OK : NS_ERROR_FAILURE;
+}
+
+static const char*
+impl_get_title (EphyX509Cert *cert)
+{
+ MozillaX509Cert *m_cert = MOZILLA_X509_CERT (cert);
+
+ /* lazy initialization of the title private variable */
+ if (m_cert->priv->title != NULL)
+ {
+ return m_cert->priv->title;
+ }
+
+ /* This title logic is adapted from Mozilla source at
+ mozilla/security/manager/ssl/src/nsCertTree.cpp */
+ nsString name;
+ m_cert->priv->mozilla_cert->GetCommonName (name);
+ if (name.Length())
+ {
+ nsCString cname;
+ NS_UTF16ToCString (name, NS_CSTRING_ENCODING_UTF8, cname);
+
+ m_cert->priv->title = g_strdup (cname.get());
+ }
+ else
+ {
+ /* No common name, so get the nickname instead */
+ nsString nick;
+ m_cert->priv->mozilla_cert->GetNickname (nick);
+
+ nsCString cnick;
+ NS_UTF16ToCString (nick, NS_CSTRING_ENCODING_UTF8, cnick);
+
+ const char * str = cnick.get();
+ char * colon = strchr (str, ':');
+ if (colon)
+ {
+ m_cert->priv->title = g_strdup (colon+1);
+ }
+ else
+ {
+ m_cert->priv->title = g_strdup (cnick.get());
+ }
+ }
+
+ return m_cert->priv->title;
+}
+
+static void
+impl_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MozillaX509Cert *cert = MOZILLA_X509_CERT (object);
+
+ switch (prop_id)
+ {
+ case PROP_MOZILLA_CERT:
+ mozilla_x509_cert_set_mozilla_cert(cert,
+ (nsIX509Cert*)g_value_get_pointer (value));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+impl_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MozillaX509Cert *cert = MOZILLA_X509_CERT (object);
+
+ switch (prop_id)
+ {
+ case PROP_MOZILLA_CERT:
+ g_value_set_pointer (value, cert->priv->mozilla_cert);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+mozilla_x509_cert_init (MozillaX509Cert *cert)
+{
+ cert->priv = MOZILLA_X509_CERT_GET_PRIVATE (cert);
+}
+
+static void
+mozilla_x509_cert_finalize (GObject *object)
+{
+ MozillaX509Cert *cert = MOZILLA_X509_CERT (object);
+
+ LOG ("Finalizing MozillaX509Cert %p", cert);
+
+ if (cert->priv->mozilla_cert)
+ {
+ NS_RELEASE (cert->priv->mozilla_cert);
+ }
+
+ if (cert->priv->title)
+ {
+ g_free (cert->priv->title);
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+ephy_x509_cert_init (EphyX509CertIface *iface)
+{
+ iface->get_title = impl_get_title;
+}
+
+static void
+mozilla_x509_cert_class_init (MozillaX509CertClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = (GObjectClass*)g_type_class_peek_parent (klass);
+
+ object_class->finalize = mozilla_x509_cert_finalize;
+ object_class->set_property = impl_set_property;
+ object_class->get_property = impl_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_MOZILLA_CERT,
+ g_param_spec_pointer ("mozilla-cert",
+ "Mozilla-Cert",
+ "Mozilla XPCOM certificate",
+ (GParamFlags)(G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)));
+
+ g_type_class_add_private (object_class, sizeof (MozillaX509CertPrivate));
+}
+
+MozillaX509Cert *
+mozilla_x509_cert_new (nsIX509Cert *moz_cert)
+{
+ MozillaX509Cert *cert;
+
+ cert = (MozillaX509Cert*)g_object_new (MOZILLA_TYPE_X509_CERT,
+ "mozilla-cert", moz_cert,
+ (char *) NULL);
+ return cert;
+}
diff --git a/embed/xulrunner/embed/mozilla-x509-cert.h b/embed/xulrunner/embed/mozilla-x509-cert.h
new file mode 100644
index 000000000..9bb61d216
--- /dev/null
+++ b/embed/xulrunner/embed/mozilla-x509-cert.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2003 Robert Marcano
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+#ifndef MOZILLA_X509_CERT_H
+#define MOZILLA_X509_CERT_H
+
+#include "ephy-x509-cert.h"
+
+#include <glib-object.h>
+
+#include <nsCOMPtr.h>
+#include <nsIX509Cert.h>
+
+G_BEGIN_DECLS
+
+#define MOZILLA_TYPE_X509_CERT (mozilla_x509_cert_get_type ())
+#define MOZILLA_X509_CERT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOZILLA_TYPE_X509_CERT, MozillaX509Cert))
+#define MOZILLA_X509_CERT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOZILLA_TYPE_X509_CERT, MozillaX509CertClass))
+#define MOZILLA_IS_X509_CERT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOZILLA_TYPE_X509_CERT))
+#define MOZILLA_IS_X509_CERT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOZILLA_TYPE_X509_CERT))
+#define MOZILLA_X509_CERT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOZILLA_TYPE_X509_CERT, MozillaX509CertClass))
+
+typedef struct _MozillaX509Cert MozillaX509Cert;
+typedef struct _MozillaX509CertPrivate MozillaX509CertPrivate;
+typedef struct _MozillaX509CertClass MozillaX509CertClass;
+
+struct _MozillaX509Cert
+{
+ GObject parent;
+ MozillaX509CertPrivate *priv;
+};
+
+struct _MozillaX509CertClass
+{
+ GObjectClass parent_class;
+};
+
+GType mozilla_x509_cert_get_type (void);
+
+MozillaX509Cert *mozilla_x509_cert_new (nsIX509Cert *aMozCert);
+
+nsresult mozilla_x509_cert_get_mozilla_cert (MozillaX509Cert *cert, nsIX509Cert **cert);
+
+G_END_DECLS
+
+#endif
diff --git a/embed/xulrunner/src/AutoJSContextStack.cpp b/embed/xulrunner/src/AutoJSContextStack.cpp
new file mode 100644
index 000000000..1e02b60fd
--- /dev/null
+++ b/embed/xulrunner/src/AutoJSContextStack.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include "AutoJSContextStack.h"
+
+#include <nsIServiceManager.h>
+#include <nsServiceManagerUtils.h>
+
+AutoJSContextStack::~AutoJSContextStack()
+{
+ if (mStack) {
+ JSContext* cx;
+ mStack->Pop (&cx);
+
+ NS_ASSERTION(cx == nsnull, "We pushed a null context but popped a non-null context!?");
+ }
+}
+
+nsresult
+AutoJSContextStack::Init()
+{
+ nsresult rv;
+ mStack = do_GetService ("@mozilla.org/js/xpc/ContextStack;1", &rv);
+ if (NS_FAILED (rv))
+ return rv;
+
+ return mStack->Push (nsnull);
+}
diff --git a/embed/xulrunner/src/AutoJSContextStack.h b/embed/xulrunner/src/AutoJSContextStack.h
new file mode 100644
index 000000000..5294e7d4e
--- /dev/null
+++ b/embed/xulrunner/src/AutoJSContextStack.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#ifndef AUTO_JSCONTEXTSTACK_H
+#define AUTO_JSCONTEXTSTACK_H
+
+struct JSContext;
+
+#include <nsCOMPtr.h>
+#include <nsIJSContextStack.h>
+
+class AutoJSContextStack
+{
+ public:
+ AutoJSContextStack () { }
+ ~AutoJSContextStack ();
+
+ nsresult Init ();
+
+ private:
+ nsCOMPtr<nsIJSContextStack> mStack;
+};
+
+#endif
diff --git a/embed/xulrunner/src/AutoWindowModalState.cpp b/embed/xulrunner/src/AutoWindowModalState.cpp
new file mode 100644
index 000000000..ca7596b38
--- /dev/null
+++ b/embed/xulrunner/src/AutoWindowModalState.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include "AutoWindowModalState.h"
+
+AutoWindowModalState::AutoWindowModalState (nsIDOMWindow *aWindow)
+{
+#ifdef HAVE_GECKO_1_9
+ mWindow = do_QueryInterface (aWindow);
+ if (mWindow) {
+ mWindow->EnterModalState ();
+ }
+#endif
+}
+
+AutoWindowModalState::~AutoWindowModalState()
+{
+#ifdef HAVE_GECKO_1_9
+ if (mWindow) {
+ mWindow->LeaveModalState ();
+ }
+#endif
+}
diff --git a/embed/xulrunner/src/AutoWindowModalState.h b/embed/xulrunner/src/AutoWindowModalState.h
new file mode 100644
index 000000000..bccefede2
--- /dev/null
+++ b/embed/xulrunner/src/AutoWindowModalState.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#ifndef AUTO_WINDOWMODALSTATE_H
+#define AUTO_WINDOWMODALSTATE_H
+
+#include <nsCOMPtr.h>
+#include <nsPIDOMWindow.h>
+
+class AutoWindowModalState
+{
+ public:
+ AutoWindowModalState (nsIDOMWindow *);
+ ~AutoWindowModalState ();
+
+ private:
+
+ nsCOMPtr<nsPIDOMWindow> mWindow;
+};
+
+#endif
diff --git a/embed/xulrunner/src/EmbedContentListener.cpp b/embed/xulrunner/src/EmbedContentListener.cpp
new file mode 100644
index 000000000..8a3280488
--- /dev/null
+++ b/embed/xulrunner/src/EmbedContentListener.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright © Christopher Blizzard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include <strings.h>
+
+#include "nsIURI.h"
+#include <nsMemory.h>
+
+#include "EmbedContentListener.h"
+#include "GeckoBrowser.h"
+#include "gecko-embed-signals.h"
+
+#include "nsServiceManagerUtils.h"
+#include "nsIWebNavigationInfo.h"
+#include "nsDocShellCID.h"
+
+EmbedContentListener::EmbedContentListener(void)
+{
+ mOwner = nsnull;
+}
+
+EmbedContentListener::~EmbedContentListener()
+{
+}
+
+NS_IMPL_ISUPPORTS2(EmbedContentListener,
+ nsIURIContentListener,
+ nsISupportsWeakReference)
+
+nsresult
+EmbedContentListener::Init(GeckoBrowser *aOwner)
+{
+ mOwner = aOwner;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::OnStartURIOpen(nsIURI *aURI,
+ PRBool *aAbortOpen)
+{
+ nsresult rv;
+
+ nsEmbedCString specString;
+ rv = aURI->GetSpec(specString);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ gboolean retval = FALSE;
+ g_signal_emit (mOwner->mOwningWidget,
+ gecko_embed_signals[OPEN_URI], 0,
+ specString.get(), &retval);
+
+ *aAbortOpen = retval;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::DoContent(const char *aContentType,
+ PRBool aIsContentPreferred,
+ nsIRequest *aRequest,
+ nsIStreamListener **aContentHandler,
+ PRBool *aAbortProcess)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::IsPreferred(const char *aContentType,
+ char **aDesiredContentType,
+ PRBool *aCanHandleContent)
+{
+ return CanHandleContent(aContentType, PR_TRUE, aDesiredContentType,
+ aCanHandleContent);
+}
+
+NS_IMETHODIMP
+EmbedContentListener::CanHandleContent(const char *aContentType,
+ PRBool aIsContentPreferred,
+ char **aDesiredContentType,
+ PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+ *aDesiredContentType = nsnull;
+
+ if (aContentType) {
+ nsCOMPtr<nsIWebNavigationInfo> webNavInfo(
+ do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID));
+ if (webNavInfo) {
+ PRUint32 canHandle;
+ nsresult rv =
+ webNavInfo->IsTypeSupported(nsDependentCString(aContentType),
+ mOwner ? mOwner->mNavigation.get() : nsnull,
+ &canHandle);
+ NS_ENSURE_SUCCESS(rv, rv);
+ *_retval = (canHandle != nsIWebNavigationInfo::UNSUPPORTED);
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::GetLoadCookie(nsISupports **aLoadCookie)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::SetLoadCookie(nsISupports *aLoadCookie)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::GetParentContentListener(nsIURIContentListener **aParent)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::SetParentContentListener(nsIURIContentListener *aParent)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/embed/xulrunner/src/EmbedContentListener.h b/embed/xulrunner/src/EmbedContentListener.h
new file mode 100644
index 000000000..427d8263e
--- /dev/null
+++ b/embed/xulrunner/src/EmbedContentListener.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright © Christopher Blizzard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef __EmbedContentListener_h
+#define __EmbedContentListener_h
+
+#include <nsIURIContentListener.h>
+#include <nsWeakReference.h>
+
+class GeckoBrowser;
+
+class EmbedContentListener : public nsIURIContentListener,
+ public nsSupportsWeakReference
+{
+ public:
+
+ EmbedContentListener();
+ virtual ~EmbedContentListener();
+
+ nsresult Init (GeckoBrowser *aOwner);
+
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIURICONTENTLISTENER
+
+ private:
+
+ GeckoBrowser *mOwner;
+
+};
+
+#endif /* __EmbedContentListener_h */
diff --git a/embed/xulrunner/src/EmbedEventListener.cpp b/embed/xulrunner/src/EmbedEventListener.cpp
new file mode 100644
index 000000000..e4803b8bd
--- /dev/null
+++ b/embed/xulrunner/src/EmbedEventListener.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include <nsCOMPtr.h>
+#include <nsIDOMMouseEvent.h>
+
+#include "nsIDOMKeyEvent.h"
+#include "nsIDOMUIEvent.h"
+
+#include "EmbedEventListener.h"
+#include "GeckoBrowser.h"
+
+#include "gecko-embed-signals.h"
+#include "gecko-dom-event.h"
+#include "gecko-dom-event-internal.h"
+#include "gecko-dom-event-private.h"
+
+EmbedEventListener::EmbedEventListener(GeckoBrowser *aOwner)
+ : mOwner(aOwner)
+{
+}
+
+EmbedEventListener::~EmbedEventListener()
+{
+}
+
+NS_IMPL_ADDREF(EmbedEventListener)
+NS_IMPL_RELEASE(EmbedEventListener)
+NS_INTERFACE_MAP_BEGIN(EmbedEventListener)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMKeyListener)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMKeyListener)
+ NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
+ NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
+ NS_INTERFACE_MAP_ENTRY(nsIDOMUIListener)
+ NS_INTERFACE_MAP_ENTRY(nsIDOMContextMenuListener)
+NS_INTERFACE_MAP_END
+
+inline NS_METHOD
+EmbedEventListener::Emit(nsIDOMEvent *aDOMEvent,
+ GeckoEmbedSignals signal,
+ GeckoDOMEventType type)
+{
+ if (!aDOMEvent)
+ return NS_OK;
+
+ // g_print ("Emitting signal '%s'\n", g_signal_name (gecko_embed_signals[signal]));
+
+ /* Check if there are any handlers connected */
+ if (!g_signal_has_handler_pending (mOwner->mOwningWidget,
+ gecko_embed_signals[signal],
+ 0, FALSE /* FIXME: correct? */)) {
+ return NS_OK;
+ }
+
+ GeckoDOMEvent event;
+ GECKO_DOM_EVENT_STATIC_INIT (event, aDOMEvent);
+
+ gboolean retval = FALSE;
+ g_signal_emit (mOwner->mOwningWidget,
+ gecko_embed_signals[signal], 0,
+ (GeckoDOMEvent*) &event, &retval);
+ if (retval) {
+ aDOMEvent->StopPropagation();
+ aDOMEvent->PreventDefault();
+ }
+
+ GECKO_DOM_EVENT_STATIC_DEINIT (event);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::KeyDown(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_KEY_DOWN, TYPE_KEY_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::KeyPress(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_KEY_PRESS, TYPE_KEY_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::KeyUp(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_KEY_UP, TYPE_KEY_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseDown(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_MOUSE_DOWN, TYPE_MOUSE_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseUp(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_MOUSE_UP, TYPE_MOUSE_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseClick(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_MOUSE_CLICK, TYPE_MOUSE_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseDblClick(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_MOUSE_DOUBLE_CLICK, TYPE_MOUSE_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseOver(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_MOUSE_OVER, TYPE_MOUSE_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseOut(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_MOUSE_OUT, TYPE_MOUSE_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::FocusIn(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_FOCUS_IN, TYPE_UI_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::FocusOut(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_FOCUS_OUT, TYPE_UI_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::Activate(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_ACTIVATE, TYPE_UI_EVENT);
+}
+
+NS_IMETHODIMP
+EmbedEventListener::ContextMenu(nsIDOMEvent* aDOMEvent)
+{
+ return Emit(aDOMEvent, DOM_CONTEXT_MENU, TYPE_MOUSE_EVENT);
+}
diff --git a/embed/xulrunner/src/EmbedEventListener.h b/embed/xulrunner/src/EmbedEventListener.h
new file mode 100644
index 000000000..e1ea99d31
--- /dev/null
+++ b/embed/xulrunner/src/EmbedEventListener.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef __EmbedEventListener_h
+#define __EmbedEventListener_h
+
+#include <nsIDOMKeyListener.h>
+#include <nsIDOMMouseListener.h>
+#include <nsIDOMUIListener.h>
+#include <nsIDOMContextMenuListener.h>
+
+#include <gecko-embed-signals.h>
+
+class GeckoBrowser;
+
+class EmbedEventListener : public nsIDOMKeyListener,
+ public nsIDOMMouseListener,
+ public nsIDOMUIListener,
+ public nsIDOMContextMenuListener
+{
+ public:
+
+ EmbedEventListener(GeckoBrowser *aOwner);
+ virtual ~EmbedEventListener();
+
+ NS_DECL_ISUPPORTS
+
+ // nsIDOMEventListener
+
+ NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; }
+
+ // nsIDOMKeyListener
+
+ NS_IMETHOD KeyDown(nsIDOMEvent* aDOMEvent);
+ NS_IMETHOD KeyUp(nsIDOMEvent* aDOMEvent);
+ NS_IMETHOD KeyPress(nsIDOMEvent* aDOMEvent);
+
+ // nsIDOMMouseListener
+
+ NS_IMETHOD MouseDown(nsIDOMEvent* aDOMEvent);
+ NS_IMETHOD MouseUp(nsIDOMEvent* aDOMEvent);
+ NS_IMETHOD MouseClick(nsIDOMEvent* aDOMEvent);
+ NS_IMETHOD MouseDblClick(nsIDOMEvent* aDOMEvent);
+ NS_IMETHOD MouseOver(nsIDOMEvent* aDOMEvent);
+ NS_IMETHOD MouseOut(nsIDOMEvent* aDOMEvent);
+
+ // nsIDOMUIListener
+
+ NS_IMETHOD Activate(nsIDOMEvent* aDOMEvent);
+ NS_IMETHOD FocusIn(nsIDOMEvent* aDOMEvent);
+ NS_IMETHOD FocusOut(nsIDOMEvent* aDOMEvent);
+
+ // nsIDOMContextMenuListener
+ NS_IMETHOD ContextMenu(nsIDOMEvent *aDOMEvent);
+
+ private:
+ GeckoBrowser *mOwner;
+
+ enum GeckoDOMEventType {
+ TYPE_KEY_EVENT,
+ TYPE_MOUSE_EVENT,
+ TYPE_UI_EVENT
+ };
+
+ NS_METHOD Emit(nsIDOMEvent *aDOMEvent,
+ GeckoEmbedSignals signal,
+ GeckoDOMEventType);
+};
+
+#endif /* __EmbedEventListener_h */
diff --git a/embed/xulrunner/src/EmbedProgress.cpp b/embed/xulrunner/src/EmbedProgress.cpp
new file mode 100644
index 000000000..d31e9f850
--- /dev/null
+++ b/embed/xulrunner/src/EmbedProgress.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include "EmbedProgress.h"
+
+#include <nsIChannel.h>
+#include <nsIWebProgress.h>
+#include <nsIDOMWindow.h>
+
+#include "nsIURI.h"
+#include "nsMemory.h"
+
+#include "gecko-embed-types.h"
+
+#include "gecko-embed-signals.h"
+
+EmbedProgress::EmbedProgress()
+: mOwner(nsnull)
+{
+}
+
+EmbedProgress::~EmbedProgress()
+{
+}
+
+/* FIXME implement nsIWebProgressListener2 */
+NS_IMPL_ISUPPORTS2(EmbedProgress,
+ nsIWebProgressListener,
+ nsISupportsWeakReference)
+
+nsresult
+EmbedProgress::Init(GeckoBrowser *aOwner)
+{
+ mOwner = aOwner;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedProgress::OnStateChange(nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRUint32 aStateFlags,
+ nsresult aStatus)
+{
+ // give the widget a chance to attach any listeners
+ mOwner->ContentStateChange();
+ // if we've got the start flag, emit the signal
+ if ((aStateFlags & GECKO_EMBED_FLAG_IS_NETWORK) &&
+ (aStateFlags & GECKO_EMBED_FLAG_START))
+ {
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[NET_START], 0);
+ }
+
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
+ if (!channel) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIURI> requestURI;
+ channel->GetURI(getter_AddRefs(requestURI));
+ if (!requestURI) return NS_ERROR_FAILURE;
+
+ if (IsCurrentURI(requestURI))
+ {
+ // for people who know what they are doing
+ g_signal_emit (mOwner->mOwningWidget,
+ gecko_embed_signals[NET_STATE], 0,
+ aStateFlags, aStatus);
+ }
+
+ nsEmbedCString uriString;
+ requestURI->GetSpec(uriString);
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[NET_STATE_ALL], 0,
+ uriString.get(), (gint)aStateFlags, (gint)aStatus);
+ // and for stop, too
+ if ((aStateFlags & GECKO_EMBED_FLAG_IS_NETWORK) &&
+ (aStateFlags & GECKO_EMBED_FLAG_STOP))
+ {
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[NET_STOP], 0);
+ // let our owner know that the load finished
+ mOwner->ContentFinishedLoading();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedProgress::OnProgressChange(nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRInt32 aCurSelfProgress,
+ PRInt32 aMaxSelfProgress,
+ PRInt32 aCurTotalProgress,
+ PRInt32 aMaxTotalProgress)
+{
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
+ if (!channel) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIURI> requestURI;
+ channel->GetURI(getter_AddRefs(requestURI));
+ if (!requestURI) return NS_ERROR_FAILURE;
+
+ // is it the same as the current uri?
+ if (IsCurrentURI(requestURI)) {
+ g_signal_emit (mOwner->mOwningWidget,
+ gecko_embed_signals[PROGRESS], 0,
+ aCurTotalProgress, aMaxTotalProgress);
+ }
+
+ nsEmbedCString uriString;
+ requestURI->GetSpec(uriString);
+ g_signal_emit (mOwner->mOwningWidget,
+ gecko_embed_signals[PROGRESS_ALL], 0,
+ uriString.get(),
+ aCurTotalProgress, aMaxTotalProgress);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedProgress::OnLocationChange(nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ nsIURI *aLocation)
+{
+ nsEmbedCString newURI;
+ NS_ENSURE_ARG_POINTER(aLocation);
+ aLocation->GetSpec(newURI);
+
+ // Make sure that this is the primary frame change and not
+ // just a subframe.
+ PRBool isSubFrameLoad = PR_FALSE;
+ if (aWebProgress) {
+ nsCOMPtr<nsIDOMWindow> domWindow;
+ nsCOMPtr<nsIDOMWindow> topDomWindow;
+
+ aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
+
+ // get the root dom window
+ if (domWindow)
+ domWindow->GetTop(getter_AddRefs(topDomWindow));
+
+ if (domWindow != topDomWindow)
+ isSubFrameLoad = PR_TRUE;
+ }
+
+ if (!isSubFrameLoad) {
+ mOwner->SetURI(newURI.get());
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[LOCATION], 0);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedProgress::OnStatusChange(nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ nsresult aStatus,
+ const PRUnichar *aMessage)
+{
+ // need to make a copy so we can safely cast to a void *
+ nsEmbedString message(aMessage);
+ PRUnichar *tmpString = NS_StringCloneData(message);
+
+ g_signal_emit (mOwner->mOwningWidget,
+ gecko_embed_signals[STATUS_CHANGE], 0,
+ static_cast<void *>(aRequest),
+ static_cast<int>(aStatus),
+ static_cast<void *>(tmpString));
+
+ nsMemory::Free(tmpString);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedProgress::OnSecurityChange(nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
+ PRUint32 aState)
+{
+ g_signal_emit (mOwner->mOwningWidget,
+ gecko_embed_signals[SECURITY_CHANGE], 0,
+ static_cast<void *>(aRequest),
+ aState);
+ return NS_OK;
+}
+
+PRBool
+EmbedProgress::IsCurrentURI(nsIURI *aURI)
+{
+ nsEmbedCString spec;
+ aURI->GetSpec(spec);
+
+ return strcmp(mOwner->mURI.get(), spec.get()) == 0;
+}
diff --git a/embed/xulrunner/src/EmbedProgress.h b/embed/xulrunner/src/EmbedProgress.h
new file mode 100644
index 000000000..ca4d2187f
--- /dev/null
+++ b/embed/xulrunner/src/EmbedProgress.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright © Christopher Blizzard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef __EmbedProgress_h
+#define __EmbedProgress_h
+
+#include <nsIWebProgressListener.h>
+#include <nsWeakReference.h>
+#include <nsIURI.h>
+#include "GeckoBrowser.h"
+
+class EmbedProgress : public nsIWebProgressListener,
+ public nsSupportsWeakReference
+{
+ public:
+ EmbedProgress();
+ virtual ~EmbedProgress();
+
+ nsresult Init(GeckoBrowser *aOwner);
+
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIWEBPROGRESSLISTENER
+
+ private:
+
+ GeckoBrowser *mOwner;
+
+ PRBool IsCurrentURI(nsIURI *aURI);
+};
+
+#endif /* __EmbedProgress_h */
diff --git a/embed/xulrunner/src/EmbedStream.cpp b/embed/xulrunner/src/EmbedStream.cpp
new file mode 100644
index 000000000..6cd08d400
--- /dev/null
+++ b/embed/xulrunner/src/EmbedStream.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright © Christopher Blizzard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include <config.h>
+
+#include <nsIPipe.h>
+#include <nsIInputStream.h>
+#include <nsIOutputStream.h>
+#include <nsIContentViewerContainer.h>
+#include <nsIDocumentLoaderFactory.h>
+#include <nsNetUtil.h>
+#include <prmem.h>
+
+#include "nsXPCOMCID.h"
+#include "nsICategoryManager.h"
+
+#include "nsIContentViewer.h"
+
+#include "EmbedStream.h"
+#include "EmbedPrivate.h"
+#include "EmbedWindow.h"
+#include "nsReadableUtils.h"
+
+// nsIInputStream interface
+
+NS_IMPL_ISUPPORTS1(EmbedStream, nsIInputStream)
+
+EmbedStream::EmbedStream()
+{
+ mOwner = nsnull;
+ mOffset = 0;
+ mDoingStream = PR_FALSE;
+}
+
+EmbedStream::~EmbedStream()
+{
+}
+
+void
+EmbedStream::InitOwner(EmbedPrivate *aOwner)
+{
+ mOwner = aOwner;
+}
+
+NS_METHOD
+EmbedStream::Init(void)
+{
+ nsresult rv = NS_OK;
+
+ nsCOMPtr<nsIInputStream> bufInStream;
+ nsCOMPtr<nsIOutputStream> bufOutStream;
+
+ rv = NS_NewPipe(getter_AddRefs(bufInStream),
+ getter_AddRefs(bufOutStream));
+
+ if (NS_FAILED(rv)) return rv;
+
+ mInputStream = bufInStream;
+ mOutputStream = bufOutStream;
+ return NS_OK;
+}
+
+NS_METHOD
+EmbedStream::OpenStream(const char *aBaseURI, const char *aContentType)
+{
+ NS_ENSURE_ARG_POINTER(aBaseURI);
+ NS_ENSURE_ARG_POINTER(aContentType);
+
+ nsresult rv = NS_OK;
+
+ // if we're already doing a stream then close the current one
+ if (mDoingStream)
+ CloseStream();
+
+ // set our state
+ mDoingStream = PR_TRUE;
+
+ // initialize our streams
+ rv = Init();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // get the content area of our web browser
+ nsCOMPtr<nsIWebBrowser> browser;
+ mOwner->mWindow->GetWebBrowser(getter_AddRefs(browser));
+
+ // get the viewer container
+ nsCOMPtr<nsIContentViewerContainer> viewerContainer;
+ viewerContainer = do_GetInterface(browser);
+
+ // create a new uri object
+ nsCOMPtr<nsIURI> uri;
+ nsCAutoString spec(aBaseURI);
+ rv = NS_NewURI(getter_AddRefs(uri), spec.get());
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ // create a new load group
+ rv = NS_NewLoadGroup(getter_AddRefs(mLoadGroup), nsnull);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // create a new input stream channel
+ rv = NS_NewInputStreamChannel(getter_AddRefs(mChannel), uri,
+ static_cast<nsIInputStream *>(this),
+ nsDependentCString(aContentType),
+ EmptyCString());
+ if (NS_FAILED(rv))
+ return rv;
+
+ // set the channel's load group
+ rv = mChannel->SetLoadGroup(mLoadGroup);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // find a document loader for this content type
+
+ nsXPIDLCString docLoaderContractID;
+ nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
+ if (NS_FAILED(rv))
+ return rv;
+ rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", aContentType,
+ getter_Copies(docLoaderContractID));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory;
+ docLoaderFactory = do_GetService(docLoaderContractID.get(), &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // ok, create an instance of the content viewer for that command and
+ // mime type
+ nsCOMPtr<nsIContentViewer> contentViewer;
+ rv = docLoaderFactory->CreateInstance("view", mChannel, mLoadGroup,
+ aContentType, viewerContainer,
+ nsnull,
+ getter_AddRefs(mStreamListener),
+ getter_AddRefs(contentViewer));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // set the container viewer container for this content view
+ rv = contentViewer->SetContainer(viewerContainer);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // embed this sucker
+ rv = viewerContainer->Embed(contentViewer, "view", nsnull);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // start our request
+ nsCOMPtr<nsIRequest> request = do_QueryInterface(mChannel);
+ rv = mStreamListener->OnStartRequest(request, NULL);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+NS_METHOD
+EmbedStream::AppendToStream(const char *aData, gint32 aLen)
+{
+ nsresult rv;
+
+ // append the data
+ rv = Append(aData, aLen);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // notify our listeners
+ nsCOMPtr<nsIRequest> request = do_QueryInterface(mChannel);
+ rv = mStreamListener->OnDataAvailable(request,
+ NULL,
+ static_cast<nsIInputStream *>(this),
+ mOffset, /* offset */
+ aLen); /* len */
+ // move our counter
+ mOffset += aLen;
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+NS_METHOD
+EmbedStream::CloseStream(void)
+{
+ nsresult rv = NS_OK;
+
+ NS_ENSURE_STATE(mDoingStream);
+ mDoingStream = PR_FALSE;
+
+ nsCOMPtr<nsIRequest> request = do_QueryInterface(mChannel, &rv);
+ if (NS_FAILED(rv))
+ goto loser;
+
+ rv = mStreamListener->OnStopRequest(request, NULL, NS_OK);
+ if (NS_FAILED(rv))
+ return rv;
+
+ loser:
+ mLoadGroup = nsnull;
+ mChannel = nsnull;
+ mStreamListener = nsnull;
+ mOffset = 0;
+
+ return rv;
+}
+
+NS_METHOD
+EmbedStream::Append(const char *aData, PRUint32 aLen)
+{
+ nsresult rv = NS_OK;
+ PRUint32 bytesWritten = 0;
+ rv = mOutputStream->Write(aData, aLen, &bytesWritten);
+ if (NS_FAILED(rv))
+ return rv;
+
+ NS_ASSERTION(bytesWritten == aLen,
+ "underlying byffer couldn't handle the write");
+ return rv;
+}
+
+NS_IMETHODIMP
+EmbedStream::Available(PRUint32 *_retval)
+{
+ return mInputStream->Available(_retval);
+}
+
+NS_IMETHODIMP
+EmbedStream::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval)
+{
+ return mInputStream->Read(aBuf, aCount, _retval);
+}
+
+NS_IMETHODIMP EmbedStream::Close(void)
+{
+ return mInputStream->Close();
+}
+
+NS_IMETHODIMP
+EmbedStream::ReadSegments(nsWriteSegmentFun aWriter, void * aClosure,
+ PRUint32 aCount, PRUint32 *_retval)
+{
+ char *readBuf = (char *)nsMemory::Alloc(aCount);
+ PRUint32 nBytes;
+
+ if (!readBuf)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = mInputStream->Read(readBuf, aCount, &nBytes);
+
+ *_retval = 0;
+
+ if (NS_SUCCEEDED(rv)) {
+ PRUint32 writeCount = 0;
+ rv = aWriter(this, aClosure, readBuf, 0, nBytes, &writeCount);
+
+ // XXX writeCount may be less than nBytes!! This is the wrong
+ // way to synthesize ReadSegments.
+ NS_ASSERTION(writeCount == nBytes, "data loss");
+
+ // errors returned from the writer end here!
+ rv = NS_OK;
+ }
+
+ nsMemory::Free(readBuf);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+EmbedStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ return mInputStream->IsNonBlocking(aNonBlocking);
+}
diff --git a/embed/xulrunner/src/EmbedStream.h b/embed/xulrunner/src/EmbedStream.h
new file mode 100644
index 000000000..bf734e134
--- /dev/null
+++ b/embed/xulrunner/src/EmbedStream.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright © Christopher Blizzard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <nsISupports.h>
+#include <nsCOMPtr.h>
+#include <nsIOutputStream.h>
+#include <nsIInputStream.h>
+#include <nsILoadGroup.h>
+#include <nsIChannel.h>
+#include <nsIStreamListener.h>
+
+class EmbedPrivate;
+
+class EmbedStream : public nsIInputStream
+{
+ public:
+
+ EmbedStream();
+ virtual ~EmbedStream();
+
+ void InitOwner (EmbedPrivate *aOwner);
+ NS_METHOD Init (void);
+
+ NS_METHOD OpenStream (const char *aBaseURI, const char *aContentType);
+ NS_METHOD AppendToStream (const char *aData, PRInt32 aLen);
+ NS_METHOD CloseStream (void);
+
+ NS_METHOD Append (const char *aData, PRUint32 aLen);
+
+ // nsISupports
+ NS_DECL_ISUPPORTS
+ // nsIInputStream
+ NS_DECL_NSIINPUTSTREAM
+
+ private:
+ nsCOMPtr<nsIOutputStream> mOutputStream;
+ nsCOMPtr<nsIInputStream> mInputStream;
+
+ nsCOMPtr<nsILoadGroup> mLoadGroup;
+ nsCOMPtr<nsIChannel> mChannel;
+ nsCOMPtr<nsIStreamListener> mStreamListener;
+
+ PRUint32 mOffset;
+ PRBool mDoingStream;
+
+ EmbedPrivate *mOwner;
+
+};
diff --git a/embed/xulrunner/src/EmbedWindow.cpp b/embed/xulrunner/src/EmbedWindow.cpp
new file mode 100644
index 000000000..15c098f28
--- /dev/null
+++ b/embed/xulrunner/src/EmbedWindow.cpp
@@ -0,0 +1,467 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include <config.h>
+
+#include <nsCWebBrowser.h>
+#include <nsIComponentManager.h>
+#include <nsComponentManagerUtils.h>
+#include <nsIDocShellTreeItem.h>
+#include "nsIWidget.h"
+
+#include "EmbedWindow.h"
+#include "GeckoBrowser.h"
+
+#include "gecko-embed-signals.h"
+
+GtkWidget *EmbedWindow::sTipWindow = nsnull;
+
+EmbedWindow::EmbedWindow(void)
+{
+ mOwner = nsnull;
+ mVisibility = PR_FALSE;
+ mIsModal = PR_FALSE;
+}
+
+EmbedWindow::~EmbedWindow(void)
+{
+ ExitModalEventLoop(PR_FALSE);
+}
+
+nsresult
+EmbedWindow::Init(GeckoBrowser *aOwner)
+{
+ // save our owner for later
+ mOwner = aOwner;
+
+ // create our nsIWebBrowser object and set up some basic defaults.
+ mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
+ if (!mWebBrowser)
+ return NS_ERROR_FAILURE;
+
+ mWebBrowser->SetContainerWindow(static_cast<nsIWebBrowserChrome *>(this));
+
+ nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(mWebBrowser);
+ item->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
+
+ return NS_OK;
+}
+
+nsresult
+EmbedWindow::CreateWindow(void)
+{
+ nsresult rv;
+ GtkWidget *ownerAsWidget = GTK_WIDGET(mOwner->mOwningWidget);
+
+ // Get the base window interface for the web browser object and
+ // create the window.
+ mBaseWindow = do_QueryInterface(mWebBrowser);
+ rv = mBaseWindow->InitWindow(GTK_WIDGET(mOwner->mOwningWidget),
+ nsnull,
+ 0, 0,
+ ownerAsWidget->allocation.width,
+ ownerAsWidget->allocation.height);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = mBaseWindow->Create();
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+void
+EmbedWindow::ReleaseChildren(void)
+{
+ ExitModalEventLoop(PR_FALSE);
+
+ mBaseWindow->Destroy();
+ mBaseWindow = 0;
+ mWebBrowser = 0;
+}
+
+// nsISupports
+
+NS_IMPL_ADDREF(EmbedWindow)
+NS_IMPL_RELEASE(EmbedWindow)
+
+NS_INTERFACE_MAP_BEGIN(EmbedWindow)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
+ NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
+ NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
+ NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
+ NS_INTERFACE_MAP_ENTRY(nsITooltipListener)
+ NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
+NS_INTERFACE_MAP_END
+
+// nsIWebBrowserChrome
+
+NS_IMETHODIMP
+EmbedWindow::SetStatus(PRUint32 aStatusType, const PRUnichar *aStatus)
+{
+ switch (aStatusType) {
+ case STATUS_SCRIPT:
+ {
+ mJSStatus = aStatus;
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[JS_STATUS], 0);
+ }
+ break;
+ case STATUS_SCRIPT_DEFAULT:
+ // Gee, that's nice.
+ break;
+ case STATUS_LINK:
+ {
+ mLinkMessage = aStatus;
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[LINK_MESSAGE], 0);
+ }
+ break;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetWebBrowser(nsIWebBrowser **aWebBrowser)
+{
+ *aWebBrowser = mWebBrowser;
+ NS_IF_ADDREF(*aWebBrowser);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetWebBrowser(nsIWebBrowser *aWebBrowser)
+{
+ mWebBrowser = aWebBrowser;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetChromeFlags(PRUint32 *aChromeFlags)
+{
+ *aChromeFlags = mOwner->mChromeMask;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetChromeFlags(PRUint32 aChromeFlags)
+{
+ mOwner->SetChromeMask(aChromeFlags);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::DestroyBrowserWindow(void)
+{
+ // mark the owner as destroyed so it won't emit events anymore.
+ mOwner->mIsDestroyed = PR_TRUE;
+
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[DESTROY_BROWSER], 0);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SizeBrowserTo(PRInt32 aCX, PRInt32 aCY)
+{
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[SIZE_TO], 0, aCX, aCY);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::ShowAsModal(void)
+{
+ mIsModal = PR_TRUE;
+ GtkWidget *toplevel;
+ toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+ gtk_grab_add(toplevel);
+ gtk_main();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::IsWindowModal(PRBool *_retval)
+{
+ *_retval = mIsModal;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::ExitModalEventLoop(nsresult aStatus)
+{
+ if (mIsModal) {
+ GtkWidget *toplevel;
+ toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+ gtk_grab_remove(toplevel);
+ mIsModal = PR_FALSE;
+ gtk_main_quit();
+ }
+ return NS_OK;
+}
+
+// nsIWebBrowserChromeFocus
+
+NS_IMETHODIMP
+EmbedWindow::FocusNextElement()
+{
+ GtkWidget *toplevel;
+ toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+ if (!GTK_WIDGET_TOPLEVEL(toplevel))
+ return NS_OK;
+
+ g_signal_emit_by_name (toplevel, "move_focus", GTK_DIR_TAB_FORWARD);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::FocusPrevElement()
+{
+ GtkWidget *toplevel;
+ toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+ if (!GTK_WIDGET_TOPLEVEL(toplevel))
+ return NS_OK;
+
+ g_signal_emit_by_name (toplevel, "move_focus", GTK_DIR_TAB_BACKWARD);
+
+ return NS_OK;
+}
+
+// nsIEmbeddingSiteWindow
+
+NS_IMETHODIMP
+EmbedWindow::SetDimensions(PRUint32 aFlags, PRInt32 aX, PRInt32 aY,
+ PRInt32 aCX, PRInt32 aCY)
+{
+ if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION &&
+ (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+ nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER))) {
+ return mBaseWindow->SetPositionAndSize(aX, aY, aCX, aCY, PR_TRUE);
+ }
+ else if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
+ return mBaseWindow->SetPosition(aX, aY);
+ }
+ else if (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+ nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER)) {
+ return mBaseWindow->SetSize(aCX, aCY, PR_TRUE);
+ }
+ return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetDimensions(PRUint32 aFlags, PRInt32 *aX,
+ PRInt32 *aY, PRInt32 *aCX, PRInt32 *aCY)
+{
+ if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION &&
+ (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+ nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER))) {
+ return mBaseWindow->GetPositionAndSize(aX, aY, aCX, aCY);
+ }
+ else if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
+ return mBaseWindow->GetPosition(aX, aY);
+ }
+ else if (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+ nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER)) {
+ return mBaseWindow->GetSize(aCX, aCY);
+ }
+ return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetFocus(void)
+{
+ // XXX might have to do more here.
+ return mBaseWindow->SetFocus();
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetTitle(PRUnichar **aTitle)
+{
+ *aTitle = NS_StringCloneData(mTitle);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetTitle(const PRUnichar *aTitle)
+{
+ mTitle = aTitle;
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[TITLE], 0);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetSiteWindow(void **aSiteWindow)
+{
+ GtkWidget *ownerAsWidget (GTK_WIDGET(mOwner->mOwningWidget));
+ *aSiteWindow = static_cast<void *>(ownerAsWidget);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetVisibility(PRBool *aVisibility)
+{
+ // Work around the problem that sometimes the window
+ // is already visible even though mVisibility isn't true
+ // yet.
+ *aVisibility = mVisibility ||
+ (!mOwner->mIsChrome &&
+ mOwner->mOwningWidget &&
+ GTK_WIDGET_MAPPED(mOwner->mOwningWidget));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetVisibility(PRBool aVisibility)
+{
+ // We always set the visibility so that if it's chrome and we finish
+ // the load we know that we have to show the window.
+ mVisibility = aVisibility;
+
+ // if this is a chrome window and the chrome hasn't finished loading
+ // yet then don't show the window yet.
+ if (mOwner->mIsChrome && !mOwner->mChromeLoaded)
+ return NS_OK;
+
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[VISIBILITY], 0,
+ aVisibility);
+ return NS_OK;
+}
+
+// nsITooltipListener
+
+static gboolean
+tooltips_paint_window (GtkWidget *window)
+{
+ // draw tooltip style border around the text
+ gtk_paint_flat_box (window->style, window->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ NULL, window, "tooltip",
+ 0, 0,
+ window->allocation.width, window->allocation.height);
+
+ return FALSE;
+}
+
+NS_IMETHODIMP
+EmbedWindow::OnShowTooltip(PRInt32 aXCoords, PRInt32 aYCoords,
+ const PRUnichar *aTipText)
+{
+ nsEmbedCString tipText;
+
+ NS_UTF16ToCString(nsEmbedString(aTipText),
+ NS_CSTRING_ENCODING_UTF8, tipText);
+
+ if (sTipWindow)
+ gtk_widget_destroy(sTipWindow);
+
+ // get the root origin for this content window
+ nsCOMPtr<nsIWidget> mainWidget;
+ mBaseWindow->GetMainWidget(getter_AddRefs(mainWidget));
+ GdkWindow *window;
+ window = static_cast<GdkWindow *>
+ (mainWidget->GetNativeData(NS_NATIVE_WINDOW));
+ gint root_x, root_y;
+ gdk_window_get_origin(window, &root_x, &root_y);
+
+ // XXX work around until I can get pink to figure out why
+ // tooltips vanish if they show up right at the origin of the
+ // cursor.
+ root_y += 10;
+
+ sTipWindow = gtk_window_new(GTK_WINDOW_POPUP);
+ gtk_widget_set_app_paintable(sTipWindow, TRUE);
+ gtk_window_set_policy(GTK_WINDOW(sTipWindow), FALSE, FALSE, TRUE);
+ // needed to get colors + fonts etc correctly
+ gtk_widget_set_name(sTipWindow, "gtk-tooltips");
+
+ // set up the popup window as a transient of the widget.
+ GtkWidget *toplevel_window;
+ toplevel_window = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+ if (!GTK_WINDOW(toplevel_window)) {
+ NS_ERROR("no gtk window in hierarchy!\n");
+ return NS_ERROR_FAILURE;
+ }
+ gtk_window_set_transient_for(GTK_WINDOW(sTipWindow),
+ GTK_WINDOW(toplevel_window));
+
+ // realize the widget
+ gtk_widget_realize(sTipWindow);
+
+ g_signal_connect (G_OBJECT(sTipWindow), "expose-event",
+ G_CALLBACK(tooltips_paint_window), NULL);
+
+ // set up the label for the tooltip
+ GtkWidget *label = gtk_label_new(tipText.get());
+ // wrap automatically
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_container_add(GTK_CONTAINER(sTipWindow), label);
+ gtk_container_set_border_width(GTK_CONTAINER(sTipWindow), 4);
+ // set the coords for the widget
+ gtk_widget_set_uposition(sTipWindow, aXCoords + root_x,
+ aYCoords + root_y);
+
+ // and show it.
+ gtk_widget_show_all(sTipWindow);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::OnHideTooltip(void)
+{
+ if (sTipWindow)
+ gtk_widget_destroy(sTipWindow);
+ sTipWindow = NULL;
+ return NS_OK;
+}
+
+// nsIInterfaceRequestor
+
+NS_IMETHODIMP
+EmbedWindow::GetInterface(const nsIID &aIID, void** aInstancePtr)
+{
+ nsresult rv;
+
+ rv = QueryInterface(aIID, aInstancePtr);
+
+ // pass it up to the web browser object
+ if (NS_FAILED(rv) || !*aInstancePtr) {
+ nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(mWebBrowser);
+ return ir->GetInterface(aIID, aInstancePtr);
+ }
+
+ return rv;
+}
diff --git a/embed/xulrunner/src/EmbedWindow.h b/embed/xulrunner/src/EmbedWindow.h
new file mode 100644
index 000000000..e03164d7e
--- /dev/null
+++ b/embed/xulrunner/src/EmbedWindow.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright © Christopher Blizzard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef __EmbedWindow_h
+#define __EmbedWindow_h
+
+#include <nsEmbedString.h>
+#include <nsIWebBrowserChrome.h>
+#include <nsIWebBrowserChromeFocus.h>
+#include <nsIEmbeddingSiteWindow.h>
+#include <nsITooltipListener.h>
+#include <nsISupports.h>
+#include <nsIWebBrowser.h>
+#include <nsIBaseWindow.h>
+#include <nsIInterfaceRequestor.h>
+#include <nsCOMPtr.h>
+
+#include <gtk/gtk.h>
+
+class GeckoBrowser;
+
+class EmbedWindow : public nsIWebBrowserChrome,
+ public nsIWebBrowserChromeFocus,
+ public nsIEmbeddingSiteWindow,
+ public nsITooltipListener,
+ public nsIInterfaceRequestor
+{
+
+ public:
+
+ EmbedWindow();
+ virtual ~EmbedWindow();
+
+ nsresult Init (GeckoBrowser *aOwner);
+ nsresult CreateWindow (void);
+ void ReleaseChildren (void);
+
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIWEBBROWSERCHROME
+
+ NS_DECL_NSIWEBBROWSERCHROMEFOCUS
+
+ NS_DECL_NSIEMBEDDINGSITEWINDOW
+
+ NS_DECL_NSITOOLTIPLISTENER
+
+ NS_DECL_NSIINTERFACEREQUESTOR
+
+ nsEmbedString mTitle;
+ nsEmbedString mJSStatus;
+ nsEmbedString mLinkMessage;
+
+ nsCOMPtr<nsIBaseWindow> mBaseWindow; // [OWNER]
+
+private:
+
+ GeckoBrowser *mOwner;
+ nsCOMPtr<nsIWebBrowser> mWebBrowser; // [OWNER]
+ static GtkWidget *sTipWindow;
+ PRBool mVisibility;
+ PRBool mIsModal;
+
+};
+
+#endif /* __EmbedWindow_h */
diff --git a/embed/xulrunner/src/EmbedWindowCreator.cpp b/embed/xulrunner/src/EmbedWindowCreator.cpp
new file mode 100644
index 000000000..1c05add95
--- /dev/null
+++ b/embed/xulrunner/src/EmbedWindowCreator.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright © Christopher Blizzard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include "EmbedWindowCreator.h"
+#include "GeckoBrowser.h"
+#include "GeckoSingle.h"
+#include "EmbedWindow.h"
+
+#include "gecko-embed-private.h"
+#include "gecko-embed-single-private.h"
+#include "gecko-embed-signals.h"
+
+EmbedWindowCreator::EmbedWindowCreator(void)
+{
+}
+
+EmbedWindowCreator::~EmbedWindowCreator()
+{
+}
+
+NS_IMPL_ISUPPORTS1(EmbedWindowCreator, nsIWindowCreator)
+
+NS_IMETHODIMP
+EmbedWindowCreator::CreateChromeWindow(nsIWebBrowserChrome *aParent,
+ PRUint32 aChromeFlags,
+ nsIWebBrowserChrome **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ GeckoEmbed *newEmbed = nsnull;
+
+ // No parent? Ask via the singleton object instead.
+ if (!aParent) {
+ gecko_embed_single_create_window(&newEmbed,
+ (guint)aChromeFlags);
+ }
+ else {
+ // Find the GeckoBrowser object for this web browser chrome object.
+ GeckoBrowser *browser = GeckoSingle::FindPrivateForBrowser(aParent);
+
+ if (!browser)
+ return NS_ERROR_FAILURE;
+
+ g_signal_emit (browser->mOwningWidget, gecko_embed_signals[NEW_WINDOW], 0,
+ &newEmbed, (guint) aChromeFlags);
+
+ }
+
+ // check to make sure that we made a new window
+ if (!newEmbed)
+ return NS_ERROR_FAILURE;
+
+ // The window _must_ be realized before we pass it back to the
+ // function that created it. Functions that create new windows
+ // will do things like GetDocShell() and the widget has to be
+ // realized before that can happen.
+ gtk_widget_realize(GTK_WIDGET(newEmbed));
+
+ GeckoBrowser *newGeckoBrowser = gecko_embed_get_GeckoBrowser (newEmbed);
+
+ // set the chrome flag on the new window if it's a chrome open
+ if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)
+ newGeckoBrowser->mIsChrome = PR_TRUE;
+
+ *_retval = static_cast<nsIWebBrowserChrome *>
+ ((newGeckoBrowser->mWindow));
+
+ if (*_retval) {
+ NS_ADDREF(*_retval);
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
diff --git a/embed/xulrunner/src/EmbedWindowCreator.h b/embed/xulrunner/src/EmbedWindowCreator.h
new file mode 100644
index 000000000..9c4e9daa5
--- /dev/null
+++ b/embed/xulrunner/src/EmbedWindowCreator.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright © Christopher Blizzard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef __EmbedWindowCreator_h
+#define __EmbedWindowCreator_h
+
+#include <nsIWindowCreator.h>
+
+class EmbedWindowCreator : public nsIWindowCreator
+{
+ public:
+ EmbedWindowCreator();
+ virtual ~EmbedWindowCreator();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIWINDOWCREATOR
+
+};
+
+#endif /* __EmbedWindowCreator_h */
diff --git a/embed/xulrunner/src/GeckoBrowser.cpp b/embed/xulrunner/src/GeckoBrowser.cpp
new file mode 100644
index 000000000..5a91a98bf
--- /dev/null
+++ b/embed/xulrunner/src/GeckoBrowser.cpp
@@ -0,0 +1,676 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include "nsIDocShell.h"
+#include "nsIWebProgress.h"
+#include "nsIWebBrowserStream.h"
+#include "nsIWebBrowserFocus.h"
+#include "nsIWidget.h"
+#include <stdlib.h>
+
+// for NS_APPSHELL_CID
+#include "nsWidgetsCID.h"
+
+// for do_GetInterface
+#include "nsIInterfaceRequestor.h"
+// for do_CreateInstance
+#include "nsIComponentManager.h"
+
+// for initializing our window watcher service
+#include "nsIWindowWatcher.h"
+
+#include "nsILocalFile.h"
+#include "nsEmbedAPI.h"
+
+// all of the crap that we need for event listeners
+// and when chrome windows finish loading
+#include "nsIDOMWindow.h"
+#include "nsPIDOMWindow.h"
+#include "nsIDOMWindowInternal.h"
+
+// For seting scrollbar visibilty
+#include <nsIDOMBarProp.h>
+
+// for the focus hacking we need to do
+#include "nsIFocusController.h"
+
+// for profiles
+#define STANDALONE_PROFILEDIRSERVICE
+#include "nsProfileDirServiceProvider.h"
+
+// app component registration
+#include "nsIGenericFactory.h"
+#include "nsIComponentRegistrar.h"
+
+// all of our local includes
+#include "GeckoBrowser.h"
+#include "EmbedWindow.h"
+#include "EmbedProgress.h"
+#include "EmbedContentListener.h"
+#include "EmbedEventListener.h"
+#include "EmbedWindowCreator.h"
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+#include "nsIAccessibilityService.h"
+#include "nsIAccessible.h"
+#include "nsIDOMDocument.h"
+#endif
+
+#include "GeckoSingle.h"
+
+GeckoBrowser::GeckoBrowser(void)
+ : mOwningWidget(nsnull)
+ , mWindow(nsnull)
+ , mProgress(nsnull)
+ , mContentListener(nsnull)
+ , mEventListener(nsnull)
+ , mChromeMask(nsIWebBrowserChrome::CHROME_ALL)
+ , mIsChrome(PR_FALSE)
+ , mChromeLoaded(PR_FALSE)
+ , mListenersAttached(PR_FALSE)
+ , mMozWindowWidget(nsnull)
+ , mIsDestroyed(PR_FALSE)
+{
+ GeckoSingle::AddBrowser(this);
+}
+
+GeckoBrowser::~GeckoBrowser()
+{
+ GeckoSingle::RemoveBrowser(this);
+}
+
+nsresult
+GeckoBrowser::Init(GeckoEmbed *aOwningWidget)
+{
+ // are we being re-initialized?
+ if (mOwningWidget)
+ return NS_OK;
+
+ // hang on with a reference to the owning widget
+ mOwningWidget = aOwningWidget;
+
+ // Create our embed window, and create an owning reference to it and
+ // initialize it. It is assumed that this window will be destroyed
+ // when we go out of scope.
+ mWindow = new EmbedWindow();
+ mWindowGuard = static_cast<nsIWebBrowserChrome *>(mWindow);
+ mWindow->Init(this);
+
+ // Create our progress listener object, make an owning reference,
+ // and initialize it. It is assumed that this progress listener
+ // will be destroyed when we go out of scope.
+ mProgress = new EmbedProgress();
+ mProgressGuard = static_cast<nsIWebProgressListener *>
+ (mProgress);
+ mProgress->Init(this);
+
+ // Create our content listener object, initialize it and attach it.
+ // It is assumed that this will be destroyed when we go out of
+ // scope.
+ mContentListener = new EmbedContentListener();
+ mContentListenerGuard = static_cast<nsISupports*>(static_cast<nsIURIContentListener*>(mContentListener));
+ mContentListener->Init(this);
+
+ // Create our key listener object and initialize it. It is assumed
+ // that this will be destroyed before we go out of scope.
+ mEventListener = new EmbedEventListener(this);
+ mEventListenerGuard =
+ static_cast<nsISupports *>(static_cast<nsIDOMKeyListener *>
+ (mEventListener));
+
+ return NS_OK;
+}
+
+nsresult
+GeckoBrowser::Realize(PRBool *aAlreadyRealized)
+{
+
+ *aAlreadyRealized = PR_FALSE;
+
+ // Have we ever been initialized before? If so then just reparent
+ // from the offscreen window.
+ if (mMozWindowWidget) {
+ gtk_widget_reparent(mMozWindowWidget, GTK_WIDGET(mOwningWidget));
+ *aAlreadyRealized = PR_TRUE;
+ return NS_OK;
+ }
+
+ // Get the nsIWebBrowser object for our embedded window.
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+ // get a handle on the navigation object
+ mNavigation = do_QueryInterface(webBrowser);
+
+ // Create our session history object and tell the navigation object
+ // to use it. We need to do this before we create the web browser
+ // window.
+ mSessionHistory = do_CreateInstance(NS_SHISTORY_CONTRACTID);
+ mNavigation->SetSessionHistory(mSessionHistory);
+
+ // create the window
+ mWindow->CreateWindow();
+
+ // bind the progress listener to the browser object
+ nsCOMPtr<nsISupportsWeakReference> supportsWeak;
+ supportsWeak = do_QueryInterface(mProgressGuard);
+ nsCOMPtr<nsIWeakReference> weakRef;
+ supportsWeak->GetWeakReference(getter_AddRefs(weakRef));
+ webBrowser->AddWebBrowserListener(weakRef,
+ NS_GET_IID (nsIWebProgressListener));
+
+ // set ourselves as the parent uri content listener
+ nsCOMPtr<nsIURIContentListener> uriListener;
+ uriListener = do_QueryInterface(mContentListenerGuard);
+ webBrowser->SetParentURIContentListener(uriListener);
+
+ // save the window id of the newly created window
+ nsCOMPtr<nsIWidget> mozWidget;
+ mWindow->mBaseWindow->GetMainWidget(getter_AddRefs(mozWidget));
+ // get the native drawing area
+ GdkWindow *tmp_window =
+ static_cast<GdkWindow *>
+ (mozWidget->GetNativeData(NS_NATIVE_WINDOW));
+ // and, thanks to superwin we actually need the parent of that.
+ // FIXME is this true on gtk2 widget?
+ tmp_window = gdk_window_get_parent(tmp_window);
+ // save the widget ID - it should be the mozarea of the window.
+ gpointer data = nsnull;
+ gdk_window_get_user_data(tmp_window, &data);
+ mMozWindowWidget = static_cast<GtkWidget *>(data);
+
+ // Apply the current chrome mask
+ ApplyChromeMask();
+
+ return NS_OK;
+}
+
+void
+GeckoBrowser::Unrealize(void)
+{
+ // reparent to our offscreen window
+ GeckoSingle::ReparentToOffscreen(mMozWindowWidget);
+}
+
+void
+GeckoBrowser::Show(void)
+{
+ // Get the nsIWebBrowser object for our embedded window.
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ mWindow->GetWebBrowser (getter_AddRefs (webBrowser));
+
+ // and set the visibility on the thing
+ nsCOMPtr<nsIBaseWindow> baseWindow (do_QueryInterface (webBrowser));
+ baseWindow->SetVisibility(PR_TRUE);
+}
+
+void
+GeckoBrowser::Hide(void)
+{
+ // Get the nsIWebBrowser object for our embedded window.
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ mWindow->GetWebBrowser (getter_AddRefs (webBrowser));
+
+ // and set the visibility on the thing
+ nsCOMPtr<nsIBaseWindow> baseWindow (do_QueryInterface (webBrowser));
+ baseWindow->SetVisibility (PR_FALSE);
+}
+
+void
+GeckoBrowser::Resize(PRUint32 aWidth, PRUint32 aHeight)
+{
+ mWindow->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION |
+ nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER,
+ 0, 0, aWidth, aHeight);
+}
+
+void
+GeckoBrowser::Destroy(void)
+{
+ // This flag might have been set from
+ // EmbedWindow::DestroyBrowserWindow() as well if someone used a
+ // window.close() or something or some other script action to close
+ // the window. No harm setting it again.
+ mIsDestroyed = PR_TRUE;
+
+ // Get the nsIWebBrowser object for our embedded window.
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+ // Release our progress listener
+ nsCOMPtr<nsISupportsWeakReference> supportsWeak
+ (do_QueryInterface(mProgressGuard));
+ nsCOMPtr<nsIWeakReference> weakRef;
+ supportsWeak->GetWeakReference(getter_AddRefs(weakRef));
+ webBrowser->RemoveWebBrowserListener(weakRef,
+ NS_GET_IID (nsIWebProgressListener));
+ weakRef = nsnull;
+ supportsWeak = nsnull;
+
+ // Release our content listener
+ webBrowser->SetParentURIContentListener(nsnull);
+ mContentListenerGuard = nsnull;
+ mContentListener = nsnull;
+
+ // Now that we have removed the listener, release our progress
+ // object
+ mProgressGuard = nsnull;
+ mProgress = nsnull;
+
+ // detach our event listeners and release the event receiver
+ DetachListeners();
+
+ mEventTarget = nsnull;
+
+ // destroy our child window
+ mWindow->ReleaseChildren();
+
+ // release navigation
+ mNavigation = nsnull;
+
+ // release session history
+ mSessionHistory = nsnull;
+
+ mOwningWidget = nsnull;
+
+ mMozWindowWidget = 0;
+}
+
+void
+GeckoBrowser::Reload(PRUint32 reloadFlags)
+{
+ /* Use the session history if it is available, this
+ * allows framesets to reload correctly */
+ nsCOMPtr<nsIWebNavigation> wn (do_QueryInterface(mSessionHistory));
+
+ if (!wn)
+ wn = mNavigation;
+
+ NS_ENSURE_TRUE (wn, );
+
+ wn->Reload(reloadFlags);
+}
+
+void
+GeckoBrowser::ApplyChromeMask()
+{
+ if (mWindow) {
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+ nsCOMPtr<nsIDOMWindow> domWindow;
+ webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
+ if (domWindow) {
+
+ nsCOMPtr<nsIDOMBarProp> scrollbars;
+ domWindow->GetScrollbars(getter_AddRefs(scrollbars));
+ if (scrollbars) {
+
+ scrollbars->SetVisible
+ (mChromeMask & nsIWebBrowserChrome::CHROME_SCROLLBARS ?
+ PR_TRUE : PR_FALSE);
+ }
+ }
+ }
+}
+
+
+void
+GeckoBrowser::SetChromeMask(PRUint32 aChromeMask)
+{
+ mChromeMask = aChromeMask;
+
+ ApplyChromeMask();
+}
+
+void
+GeckoBrowser::SetURI(const char *aURI)
+{
+ mURI = aURI;
+}
+
+void
+GeckoBrowser::LoadCurrentURI(void)
+{
+ if (mURI.Length()) {
+ nsCOMPtr<nsPIDOMWindow> piWin;
+ GetPIDOMWindow(getter_AddRefs(piWin));
+ nsAutoPopupStatePusher popupStatePusher(piWin, openAllowed);
+
+ nsEmbedString uri;
+ NS_CStringToUTF16(mURI, NS_CSTRING_ENCODING_UTF8, uri);
+ mNavigation->LoadURI(uri.get(), // URI string
+ nsIWebNavigation::LOAD_FLAGS_NONE, // Load flags
+ nsnull, // Referring URI
+ nsnull, // Post data
+ nsnull); // extra headers
+ }
+}
+
+#if 0
+nsresult
+GeckoBrowser::OpenStream(const char *aBaseURI, const char *aContentType)
+{
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+ nsCOMPtr<nsIWebBrowserStream> wbStream = do_QueryInterface(webBrowser);
+ if (!wbStream) return NS_ERROR_FAILURE;
+
+ return wbStream->OpenStream(aBaseURI, aContentType);
+}
+
+nsresult
+GeckoBrowser::AppendToStream(const char *aData, PRInt32 aLen)
+{
+ // Attach listeners to this document since in some cases we don't
+ // get updates for content added this way.
+ ContentStateChange();
+
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+ nsCOMPtr<nsIWebBrowserStream> wbStream = do_QueryInterface(webBrowser);
+ if (!wbStream) return NS_ERROR_FAILURE;
+
+ return wbStream->AppendToStream(aData, aLen);
+}
+
+nsresult
+GeckoBrowser::CloseStream(void)
+{
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+ nsCOMPtr<nsIWebBrowserStream> wbStream = do_QueryInterface(webBrowser);
+ if (!wbStream) return NS_ERROR_FAILURE;
+
+ return wbStream->CloseStream();
+}
+#endif
+
+void
+GeckoBrowser::ContentStateChange(void)
+{
+
+ // we don't attach listeners to chrome
+ if (mListenersAttached && !mIsChrome)
+ return;
+
+ GetListener();
+
+ if (!mEventTarget)
+ return;
+
+ AttachListeners();
+
+}
+
+void
+GeckoBrowser::ContentFinishedLoading(void)
+{
+ if (mIsChrome) {
+ // We're done loading.
+ mChromeLoaded = PR_TRUE;
+
+ // get the web browser
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+ // get the content DOM window for that web browser
+ nsCOMPtr<nsIDOMWindow> domWindow;
+ webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
+ if (!domWindow) {
+ NS_WARNING("no dom window in content finished loading\n");
+ return;
+ }
+
+ // resize the content
+ domWindow->SizeToContent();
+
+ // and since we're done loading show the window, assuming that the
+ // visibility flag has been set.
+ PRBool visibility;
+ mWindow->GetVisibility(&visibility);
+ if (visibility)
+ mWindow->SetVisibility(PR_TRUE);
+ }
+}
+
+void
+GeckoBrowser::ChildFocusIn(void)
+{
+ if (mIsDestroyed)
+ return;
+
+ nsresult rv;
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ rv = mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+ if (NS_FAILED(rv))
+ return;
+
+ nsCOMPtr<nsIWebBrowserFocus> webBrowserFocus(do_QueryInterface(webBrowser));
+ if (!webBrowserFocus)
+ return;
+
+ webBrowserFocus->Activate();
+}
+
+void
+GeckoBrowser::ChildFocusOut(void)
+{
+ if (mIsDestroyed)
+ return;
+
+ nsresult rv;
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ rv = mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+ if (NS_FAILED(rv))
+ return;
+
+ nsCOMPtr<nsIWebBrowserFocus> webBrowserFocus(do_QueryInterface(webBrowser));
+ if (!webBrowserFocus)
+ return;
+
+ webBrowserFocus->Deactivate();
+}
+
+// Get the event listener for the chrome event handler.
+
+void
+GeckoBrowser::GetListener(void)
+{
+ if (mEventTarget)
+ return;
+
+ nsCOMPtr<nsPIDOMWindow> piWin;
+ GetPIDOMWindow(getter_AddRefs(piWin));
+
+ if (!piWin)
+ return;
+
+ mEventTarget = do_QueryInterface(piWin->GetChromeEventHandler());
+}
+
+// attach key and mouse event listeners
+
+void
+GeckoBrowser::AttachListeners(void)
+{
+ if (!mEventTarget || mListenersAttached)
+ return;
+
+ nsIDOMEventListener *eventListener =
+ static_cast<nsIDOMEventListener *>
+ (static_cast<nsIDOMKeyListener *>(mEventListener));
+
+ // add the key listener
+ nsresult rv;
+ rv = mEventTarget->AddEventListenerByIID(eventListener,
+ NS_GET_IID(nsIDOMKeyListener));
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to add key listener\n");
+ return;
+ }
+
+ rv = mEventTarget->AddEventListenerByIID(eventListener,
+ NS_GET_IID(nsIDOMMouseListener));
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to add mouse listener\n");
+ return;
+ }
+
+ rv = mEventTarget->AddEventListenerByIID(eventListener,
+ NS_GET_IID(nsIDOMUIListener));
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to add UI listener\n");
+ return;
+ }
+
+ rv = mEventTarget->AddEventListenerByIID(eventListener,
+ NS_GET_IID(nsIDOMContextMenuListener));
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to add context menu listener\n");
+ return;
+ }
+
+ // ok, all set.
+ mListenersAttached = PR_TRUE;
+}
+
+void
+GeckoBrowser::DetachListeners(void)
+{
+ if (!mListenersAttached || !mEventTarget)
+ return;
+
+ nsIDOMEventListener *eventListener =
+ static_cast<nsIDOMEventListener *>
+ (static_cast<nsIDOMKeyListener *>(mEventListener));
+
+ nsresult rv;
+ rv = mEventTarget->RemoveEventListenerByIID(eventListener,
+ NS_GET_IID(nsIDOMKeyListener));
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to remove key listener\n");
+ return;
+ }
+
+ rv =
+ mEventTarget->RemoveEventListenerByIID(eventListener,
+ NS_GET_IID(nsIDOMMouseListener));
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to remove mouse listener\n");
+ return;
+ }
+
+ rv = mEventTarget->RemoveEventListenerByIID(eventListener,
+ NS_GET_IID(nsIDOMUIListener));
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to remove UI listener\n");
+ return;
+ }
+
+ rv = mEventTarget->RemoveEventListenerByIID(eventListener,
+ NS_GET_IID(nsIDOMContextMenuListener));
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to remove context menu listener\n");
+ return;
+ }
+
+ mListenersAttached = PR_FALSE;
+}
+
+nsresult
+GeckoBrowser::GetPIDOMWindow(nsPIDOMWindow **aPIWin)
+{
+ *aPIWin = nsnull;
+
+ // get the web browser
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+ // get the content DOM window for that web browser
+ nsCOMPtr<nsIDOMWindow> domWindow;
+ webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
+ if (!domWindow)
+ return NS_ERROR_FAILURE;
+
+ // get the private DOM window
+ nsCOMPtr<nsPIDOMWindow> domWindowPrivate = do_QueryInterface(domWindow);
+ // and the root window for that DOM window
+ *aPIWin = domWindowPrivate->GetPrivateRoot();
+
+ if (*aPIWin) {
+ NS_ADDREF(*aPIWin);
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+// FIXME does this REALLY work with frames?
+void *
+GeckoBrowser::GetAtkObjectForCurrentDocument()
+{
+ if (!mNavigation)
+ return nsnull;
+
+ nsCOMPtr<nsIAccessibilityService> accService =
+ do_GetService("@mozilla.org/accessibilityService;1");
+ if (accService) {
+ //get current document
+ nsCOMPtr<nsIDOMDocument> domDoc;
+ mNavigation->GetDocument(getter_AddRefs(domDoc));
+ NS_ENSURE_TRUE(domDoc, nsnull);
+
+ nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(domDoc));
+ NS_ENSURE_TRUE(domNode, nsnull);
+
+ nsCOMPtr<nsIAccessible> acc;
+ accService->GetAccessibleFor(domNode, getter_AddRefs(acc));
+ NS_ENSURE_TRUE(acc, nsnull);
+
+ void *atkObj = nsnull;
+ if (NS_SUCCEEDED(acc->GetNativeInterface(&atkObj)))
+ return atkObj;
+ }
+ return nsnull;
+}
+#endif /* MOZ_ACCESSIBILITY_ATK */
diff --git a/embed/xulrunner/src/GeckoBrowser.h b/embed/xulrunner/src/GeckoBrowser.h
new file mode 100644
index 000000000..0d7a86af3
--- /dev/null
+++ b/embed/xulrunner/src/GeckoBrowser.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef __GeckoBrowser_h
+#define __GeckoBrowser_h
+
+#include <nsCOMPtr.h>
+#include <nsEmbedString.h>
+#include <nsIWebNavigation.h>
+#include <nsISHistory.h>
+// for our one function that gets the GeckoBrowser via the chrome
+// object.
+#include <nsIWebBrowserChrome.h>
+#include <nsIAppShell.h>
+#include <nsPIDOMEventTarget.h>
+// app component registration
+#include <nsIGenericFactory.h>
+#include <nsIComponentRegistrar.h>
+
+#include "gecko-embed.h"
+
+class EmbedProfile;
+class EmbedProgress;
+class EmbedWindow;
+class EmbedContentListener;
+class EmbedEventListener;
+
+class nsPIDOMWindow;
+class nsIDirectoryServiceProvider;
+class nsProfileDirServiceProvider;
+
+class GeckoBrowser {
+
+ public:
+
+ GeckoBrowser();
+ ~GeckoBrowser();
+
+ nsresult Init (GeckoEmbed *aOwningWidget);
+ nsresult Realize (PRBool *aAlreadRealized);
+ void Unrealize (void);
+ void Show (void);
+ void Hide (void);
+ void Resize (PRUint32 aWidth, PRUint32 aHeight);
+ void Destroy (void);
+ void SetURI (const char *aURI);
+ void LoadCurrentURI (void);
+ void Reload (PRUint32 reloadFlags);
+
+ void SetChromeMask (PRUint32 chromeMask);
+ void ApplyChromeMask ();
+
+ nsresult OpenStream (const char *aBaseURI, const char *aContentType);
+ nsresult AppendToStream (const char *aData, PRInt32 aLen);
+ nsresult CloseStream (void);
+
+ // This is an upcall that will come from the progress listener
+ // whenever there is a content state change. We need this so we can
+ // attach event listeners.
+ void ContentStateChange (void);
+
+ // This is an upcall from the progress listener when content is
+ // finished loading. We have this so that if it's chrome content
+ // that we can size to content properly and show ourselves if
+ // visibility is set.
+ void ContentFinishedLoading(void);
+
+ // these let the widget code know when the toplevel window gets and
+ // looses focus.
+ void TopLevelFocusIn (void);
+ void TopLevelFocusOut(void);
+
+ // these are when the widget itself gets focus in and focus out
+ // events
+ void ChildFocusIn (void);
+ void ChildFocusOut(void);
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+ void *GetAtkObjectForCurrentDocument();
+#endif
+
+ GeckoEmbed *mOwningWidget;
+
+ // all of the objects that we own
+ EmbedWindow *mWindow;
+ nsCOMPtr<nsISupports> mWindowGuard;
+ EmbedProgress *mProgress;
+ nsCOMPtr<nsISupports> mProgressGuard;
+ EmbedContentListener *mContentListener;
+ nsCOMPtr<nsISupports> mContentListenerGuard;
+ EmbedEventListener *mEventListener;
+ nsCOMPtr<nsISupports> mEventListenerGuard;
+
+ nsCOMPtr<nsIWebNavigation> mNavigation;
+ nsCOMPtr<nsISHistory> mSessionHistory;
+
+ // our event receiver
+ nsCOMPtr<nsPIDOMEventTarget> mEventTarget;
+
+ // the currently loaded uri
+ nsEmbedCString mURI;
+
+ // chrome mask
+ PRUint32 mChromeMask;
+ // is this a chrome window?
+ PRBool mIsChrome;
+ // has the chrome finished loading?
+ PRBool mChromeLoaded;
+ // saved window ID for reparenting later
+ GtkWidget *mMozWindowWidget;
+ // has someone called Destroy() on us?
+ PRBool mIsDestroyed;
+
+ private:
+
+ // is the chrome listener attached yet?
+ PRBool mListenersAttached;
+
+ void GetListener (void);
+ void AttachListeners (void);
+ void DetachListeners (void);
+
+ // this will get the PIDOMWindow for this widget
+ nsresult GetPIDOMWindow (nsPIDOMWindow **aPIWin);
+};
+
+#endif /* __GeckoBrowser_h */
diff --git a/embed/xulrunner/src/GeckoPromptService.cpp b/embed/xulrunner/src/GeckoPromptService.cpp
new file mode 100644
index 000000000..c9c5b03c2
--- /dev/null
+++ b/embed/xulrunner/src/GeckoPromptService.cpp
@@ -0,0 +1,891 @@
+/*
+ * Copyright © 2005, 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <nsStringAPI.h>
+
+#include <nsCOMPtr.h>
+#include <nsIDOMWindow.h>
+#include <nsServiceManagerUtils.h>
+
+#include "gecko-embed.h"
+#include "gecko-embed-single.h"
+
+#include "AutoJSContextStack.h"
+#include "AutoWindowModalState.h"
+#include "GeckoUtils.h"
+
+#include "GeckoPromptService.h"
+
+#define TIMEOUT 1000 /* ms */
+#define TIMEOUT_DATA_KEY "timeout"
+
+#define MAX_MESSAGE_LENGTH 512
+#define MAX_TITLE_LENGTH 256
+#define MAX_BUTTON_TEXT_LENGTH 128
+
+enum
+{
+ RESPONSE_ABORT_SCRIPT = 42
+};
+
+class Prompter
+{
+public:
+ Prompter (const char*, nsIDOMWindow*, const PRUnichar*, const PRUnichar*);
+ ~Prompter();
+
+ void AddStockButton (const char*, int);
+ void AddButtonWithFlags (PRInt32, PRUint32, const PRUnichar*, PRUint32);
+ void AddButtonsWithFlags (PRUint32, const PRUnichar*, const PRUnichar*, const PRUnichar*);
+ void AddCheckbox (const PRUnichar*, PRBool*);
+ void GetCheckboxState (PRBool *);
+ void AddEntry (const char *, const PRUnichar *, PRBool);
+ void GetText (PRUint32, PRUnichar **);
+ void AddSelect (PRUint32, const PRUnichar **, PRInt32);
+ void GetSelected (PRInt32*);
+
+ PRInt32 Run (PRBool * = nsnull);
+ void Show ();
+
+ PRBool IsCalledFromScript ();
+ void PerformScriptAbortion ();
+
+ char *ConvertAndTruncateString (const PRUnichar *, PRInt32 = -1);
+ char* ConvertAndEscapeButtonText (const PRUnichar *, PRInt32 = -1);
+
+private:
+ nsCOMPtr<nsIDOMWindow> mWindow;
+ GtkDialog *mDialog;
+ GtkWidget *mVBox;
+ GtkWidget *mCheck;
+ GtkSizeGroup *mSizeGroup;
+ GtkWidget *mEntries[2];
+ GtkWidget *mCombo;
+ PRInt32 mNumButtons;
+ PRInt32 mNumEntries;
+ PRInt32 mDefaultResponse;
+ PRInt32 mUnaffirmativeResponse;
+ PRInt32 mResponse;
+ PRBool mSuccess;
+ PRBool mDelay;
+};
+
+Prompter::Prompter (const char *aStock,
+ nsIDOMWindow *aParent,
+ const PRUnichar *aTitle,
+ const PRUnichar *aText)
+ : mWindow (aParent)
+ , mDialog(nsnull)
+ , mVBox(nsnull)
+ , mCheck(nsnull)
+ , mSizeGroup(nsnull)
+ , mCombo(nsnull)
+ , mNumButtons(0)
+ , mNumEntries(0)
+ , mDefaultResponse(GTK_RESPONSE_ACCEPT)
+ , mUnaffirmativeResponse(0)
+ , mResponse(GTK_RESPONSE_CANCEL)
+ , mSuccess(PR_FALSE)
+ , mDelay(PR_FALSE)
+{
+ GtkWidget *parent, *hbox, *label, *image;
+
+ gecko_embed_single_push_startup ();
+
+ mEntries[0] = mEntries[1] = nsnull;
+
+ mDialog = GTK_DIALOG (gtk_dialog_new ());
+ g_object_ref (mDialog);
+ gtk_object_sink (GTK_OBJECT (mDialog));
+
+ char *title = NULL;
+ if (aTitle)
+ {
+ title = ConvertAndTruncateString (aTitle, MAX_TITLE_LENGTH);
+ }
+
+ gtk_window_set_title (GTK_WINDOW (mDialog), title ? title : "");
+ g_free (title);
+
+ gtk_window_set_modal (GTK_WINDOW (mDialog), TRUE);
+
+ parent = GeckoUtils::GetGtkWindowForDOMWindow (aParent);
+ if (GTK_IS_WINDOW (parent))
+ {
+ gtk_window_set_transient_for (GTK_WINDOW (mDialog),
+ GTK_WINDOW (parent));
+
+#if !GTK_CHECK_VERSION (2,9,0)
+ if (GTK_WINDOW (parent)->group)
+ {
+ gtk_window_group_add_window (GTK_WINDOW (parent)->group,
+ GTK_WINDOW (mDialog));
+ }
+#endif
+ }
+
+ gtk_dialog_set_has_separator (mDialog, FALSE);
+ gtk_window_set_resizable (GTK_WINDOW (mDialog), FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (mDialog), 5);
+ gtk_box_set_spacing (GTK_BOX (mDialog->vbox), 14); /* 2 * 5 + 14 = 24 */
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (mDialog)->vbox), hbox);
+
+ image = gtk_image_new_from_stock (aStock, GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+
+ mVBox = gtk_vbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (hbox), mVBox, TRUE, TRUE, 0);
+
+ char *text = NULL;
+ if (aText)
+ {
+ text = ConvertAndTruncateString (aText, MAX_MESSAGE_LENGTH);
+ }
+
+ label = gtk_label_new (text);
+ g_free (text);
+
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ /* Guard against overlong nonbreakable text (exploit) */
+ gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR);
+ gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+
+ gtk_box_pack_start (GTK_BOX (mVBox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ if (IsCalledFromScript ())
+ {
+ gtk_dialog_add_button (GTK_DIALOG (mDialog),
+ _("_Abort Script"),
+ RESPONSE_ABORT_SCRIPT);
+ }
+
+ gtk_widget_show (image);
+ gtk_widget_show (mVBox);
+ gtk_widget_show (hbox);
+}
+
+Prompter::~Prompter ()
+{
+ if (mSizeGroup)
+ {
+ g_object_unref (mSizeGroup);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (mDialog));
+ g_object_unref (mDialog);
+
+ gecko_embed_single_pop_startup ();
+}
+
+void
+Prompter::AddStockButton (const char *aStock,
+ int aResponse)
+{
+ gtk_dialog_add_button (GTK_DIALOG (mDialog),
+ aStock, aResponse);
+ ++mNumButtons;
+}
+
+void
+Prompter::AddButtonWithFlags (PRInt32 aNum,
+ PRUint32 aFlags,
+ const PRUnichar *aText,
+ PRUint32 aDefault)
+{
+ if (aFlags == 0) return;
+
+ const char *label = NULL;
+ char *freeme = NULL;
+ gboolean isAffirmative = FALSE;
+ switch (aFlags)
+ {
+ case nsIPromptService::BUTTON_TITLE_OK:
+ label = GTK_STOCK_OK;
+ isAffirmative = TRUE;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_CANCEL:
+ label = GTK_STOCK_CANCEL;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_YES:
+ label = GTK_STOCK_YES;
+ isAffirmative = TRUE;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_NO:
+ label = GTK_STOCK_NO;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_SAVE:
+ label = GTK_STOCK_SAVE;
+ isAffirmative = TRUE;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_DONT_SAVE:
+ label = _("Don't Save");
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_REVERT:
+ label = GTK_STOCK_REVERT_TO_SAVED;
+ break;
+
+ case nsIPromptService::BUTTON_TITLE_IS_STRING:
+ default:
+ label = freeme = ConvertAndEscapeButtonText (aText, MAX_BUTTON_TEXT_LENGTH);
+ /* We can't tell, so assume it's affirmative */
+ isAffirmative = TRUE;
+ break;
+ }
+
+ if (label == NULL) return;
+
+ gtk_dialog_add_button (mDialog, label, aNum);
+ ++mNumButtons;
+
+ if (isAffirmative && mDelay)
+ {
+ gtk_dialog_set_response_sensitive (mDialog, aNum, FALSE);
+ }
+
+ if (!isAffirmative)
+ {
+ mUnaffirmativeResponse = aNum;
+ }
+
+ if (aDefault)
+ {
+ mDefaultResponse = aNum;
+ }
+
+ g_free (freeme);
+}
+
+void
+Prompter::AddButtonsWithFlags (PRUint32 aFlags,
+ const PRUnichar *aText0,
+ const PRUnichar *aText1,
+ const PRUnichar *aText2)
+{
+ mDelay = (aFlags & nsIPromptService::BUTTON_DELAY_ENABLE) != 0;
+ mDefaultResponse = -1;
+
+ /* Reverse the order, on the assumption that what we passed is the
+ * 'windows' button order, and we want HIG order.
+ */
+ AddButtonWithFlags (2, ((aFlags / nsIPromptService::BUTTON_POS_2) & 0xff), aText2,
+ aFlags & nsIPromptService::BUTTON_POS_2_DEFAULT);
+ AddButtonWithFlags (1, ((aFlags / nsIPromptService::BUTTON_POS_1) & 0xff), aText1,
+ aFlags & nsIPromptService::BUTTON_POS_1_DEFAULT);
+ AddButtonWithFlags (0, ((aFlags / nsIPromptService::BUTTON_POS_0) & 0xff), aText0,
+ aFlags & nsIPromptService::BUTTON_POS_0_DEFAULT);
+
+ /* If no default was set, use the 'rightmost' unaffirmative response.
+ * This happens with the suite's password manager prompt.
+ */
+ if (mDefaultResponse == -1)
+ {
+ mDefaultResponse = mUnaffirmativeResponse;
+ }
+}
+
+void
+Prompter::AddCheckbox (const PRUnichar *aText,
+ PRBool *aState)
+{
+ if (!aState || !aText) return;
+
+ char *label = ConvertAndEscapeButtonText (aText, 2 * MAX_BUTTON_TEXT_LENGTH);
+ mCheck = gtk_check_button_new_with_mnemonic (label);
+ g_free (label);
+
+ gtk_label_set_line_wrap (GTK_LABEL (GTK_BIN (mCheck)->child), TRUE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mCheck), *aState);
+ gtk_box_pack_start (GTK_BOX (mVBox), mCheck, FALSE, FALSE, 0);
+ gtk_widget_show (mCheck);
+}
+
+void
+Prompter::GetCheckboxState (PRBool *aState)
+{
+ if (!aState || !mCheck) return;
+
+ *aState = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mCheck));
+}
+
+void
+Prompter::AddEntry (const char *aLabel,
+ const PRUnichar *aValue,
+ PRBool aIsPassword)
+{
+ if (!mSizeGroup)
+ {
+ mSizeGroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ }
+
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (mVBox), hbox, FALSE, FALSE, 0);
+
+ GtkWidget *label = nsnull;
+ if (aLabel)
+ {
+ label = gtk_label_new_with_mnemonic (aLabel);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_size_group_add_widget (mSizeGroup, label);
+ }
+
+ GtkWidget *entry = mEntries[mNumEntries++] = gtk_entry_new ();
+ gtk_entry_set_visibility (GTK_ENTRY (entry), !aIsPassword);
+ gtk_entry_set_activates_default(GTK_ENTRY (entry), TRUE);
+
+ if (aValue)
+ {
+ nsCString cValue;
+ NS_UTF16ToCString (nsDependentString(aValue),
+ NS_CSTRING_ENCODING_UTF8, cValue);
+
+ gtk_entry_set_text (GTK_ENTRY (entry), cValue.get());
+ }
+
+ if (label)
+ {
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+ }
+
+ gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+}
+
+void
+Prompter::GetText (PRUint32 aNum,
+ PRUnichar **aValue)
+{
+ if (!aValue || !mEntries[aNum]) return;
+
+ const char *text = gtk_entry_get_text (GTK_ENTRY (mEntries[aNum]));
+ if (!text) return;
+
+ nsString value;
+ NS_CStringToUTF16 (nsDependentCString (text),
+ NS_CSTRING_ENCODING_UTF8, value);
+
+ *aValue = NS_StringCloneData (value);
+}
+
+void
+Prompter::AddSelect (PRUint32 aCount,
+ const PRUnichar **aList,
+ PRInt32 aDefault)
+{
+ mCombo = gtk_combo_box_new_text ();
+
+ for (PRUint32 i = 0; i < aCount; i++)
+ {
+ /* FIXME: use "" instead in this case? */
+ if (!aList[i] || !aList[i][0]) continue;
+
+ nsCString cData;
+ NS_UTF16ToCString (nsDependentString(aList[i]), NS_CSTRING_ENCODING_UTF8, cData);
+
+ gtk_combo_box_append_text (GTK_COMBO_BOX (mCombo), cData.get());
+ }
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (mCombo), aDefault);
+
+ gtk_box_pack_start (GTK_BOX (mVBox), mCombo, FALSE, FALSE, 0);
+ gtk_widget_show (mCombo);
+}
+
+void
+Prompter::GetSelected (PRInt32 *aSelected)
+{
+ if (!aSelected || !mCombo) return;
+
+ *aSelected = gtk_combo_box_get_active (GTK_COMBO_BOX (mCombo));
+}
+
+static gboolean
+EnableResponse (GtkDialog *aDialog)
+{
+ g_object_steal_data (G_OBJECT (aDialog), TIMEOUT_DATA_KEY);
+
+ gtk_dialog_set_response_sensitive (aDialog, 0, TRUE);
+ gtk_dialog_set_response_sensitive (aDialog, 1, TRUE);
+ gtk_dialog_set_response_sensitive (aDialog, 2, TRUE);
+
+ return FALSE;
+}
+
+static void
+RemoveTimeout (gpointer idptr)
+{
+ guint timeout = GPOINTER_TO_UINT (idptr);
+
+ g_return_if_fail (timeout != 0);
+
+ g_source_remove (timeout);
+}
+
+PRInt32
+Prompter::Run (PRBool *aSuccess)
+{
+#if 0
+ AutoEventQueue queue;
+ if (NS_FAILED (queue.Init()))
+ {
+ if (aSuccess)
+ {
+ *aSuccess = PR_FALSE;
+ }
+ mSuccess = PR_FALSE;
+
+ return GTK_RESPONSE_CANCEL;
+ }
+#endif
+
+ nsresult rv;
+ AutoJSContextStack stack;
+ rv = stack.Init ();
+ if (NS_FAILED (rv)) return rv;
+
+ AutoWindowModalState modalState (mWindow);
+
+ if (mDelay)
+ {
+ guint timeout = g_timeout_add (TIMEOUT,
+ (GSourceFunc) EnableResponse,
+ mDialog);
+ g_object_set_data_full (G_OBJECT (mDialog), TIMEOUT_DATA_KEY,
+ GUINT_TO_POINTER (timeout),
+ (GDestroyNotify) RemoveTimeout);
+ }
+
+ gtk_dialog_set_default_response (GTK_DIALOG (mDialog), mDefaultResponse);
+
+ GtkWidget *widget = GTK_WIDGET (mDialog);
+ gtk_widget_show (widget);
+ mResponse = gtk_dialog_run (mDialog);
+ gtk_widget_hide (widget);
+
+ g_object_set_data (G_OBJECT (mDialog), TIMEOUT_DATA_KEY, NULL);
+
+ mSuccess = (GTK_RESPONSE_ACCEPT == mResponse);
+ if (aSuccess)
+ {
+ *aSuccess = mSuccess;
+ }
+
+ if (mResponse == RESPONSE_ABORT_SCRIPT)
+ {
+ PerformScriptAbortion ();
+ }
+
+ return mResponse;
+}
+
+static void
+DeletePrompter (gpointer aPromptPtr,
+ GObject *aZombie)
+{
+ Prompter *prompt = static_cast<Prompter*>(aPromptPtr);
+
+ delete prompt;
+}
+
+void
+Prompter::Show ()
+{
+ /* We don't need it anymore */
+ mWindow = nsnull;
+
+ gtk_window_set_modal (GTK_WINDOW (mDialog), FALSE);
+
+ g_signal_connect (mDialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ g_object_weak_ref (G_OBJECT (mDialog),
+ (GWeakNotify) DeletePrompter,
+ static_cast<gpointer>(this));
+
+ gtk_widget_show (GTK_WIDGET (mDialog));
+}
+
+PRBool
+Prompter::IsCalledFromScript()
+{
+#if 0
+ nsCOMPtr<nsIXPConnect> xpconnect (do_GetService (nsIXPConnect::GetCID()));
+ NS_ENSURE_TRUE (xpconnect, PR_FALSE);
+
+ nsresult rv;
+ nsCOMPtr<nsIXPCNativeCallContext> ncc;
+ rv = xpconnect->GetCurrentNativeCallContext (getter_AddRefs (ncc));
+ NS_ENSURE_SUCCESS (rv, PR_FALSE);
+
+ if (!ncc) return PR_FALSE;
+
+ JSContext *cx = nsnull;
+ rv = ncc->GetJSContext (&cx);
+ g_print ("GetJSContext rv=%x, cx=%p\n", rv, cx);
+
+ NS_ENSURE_SUCCESS (rv, PR_FALSE);
+
+ return cx != nsnull;
+#endif
+ return PR_FALSE;
+}
+
+void
+Prompter::PerformScriptAbortion()
+{
+#if 0
+ /* FIXME: can we only stop the calling script, not all scripts in the context? */
+
+ nsCOMPtr<nsIXPConnect> xpconnect (do_GetService (nsIXPConnect::GetCID()));
+ NS_ENSURE_TRUE (xpconnect, );
+
+ nsresult rv;
+ nsCOMPtr<nsIXPCNativeCallContext> ncc;
+ rv = xpconnect->GetCurrentNativeCallContext (getter_AddRefs (ncc));
+ NS_ENSURE_SUCCESS (rv, );
+ NS_ENSURE_TRUE (ncc, );
+
+ JSContext *cx = nsnull;
+ rv = ncc->GetJSContext (&cx);
+ g_print ("GetJSContext rv=%x, cx=%p\n", rv, cx);
+ NS_ENSURE_SUCCESS (rv, );
+ NS_ENSURE_TRUE (cx, );
+
+ g_print ("Would now disable scripts\n");
+// MozillaPrivate::SetScriptsEnabled (cx, PR_FALSE, PR_FALSE);
+#endif
+}
+
+char *
+Prompter::ConvertAndTruncateString (const PRUnichar *aText,
+ PRInt32 aMaxLength)
+{
+ if (aText == nsnull) return NULL;
+
+ /* This depends on the assumption that
+ * typeof(PRUnichar) == typeof (gunichar2) == uint16,
+ * which should be pretty safe.
+ */
+ glong n_read = 0, n_written = 0;
+ char *converted = g_utf16_to_utf8 ((gunichar2*) aText, aMaxLength,
+ &n_read, &n_written, NULL);
+ /* FIXME loop from the end while !g_unichar_isspace (char)? */
+
+ return converted;
+}
+
+char *
+Prompter::ConvertAndEscapeButtonText(const PRUnichar *aText,
+ PRInt32 aMaxLength)
+{
+ char *converted = ConvertAndTruncateString (aText, aMaxLength);
+ if (converted == NULL) return NULL;
+
+ char *escaped = (char*) g_malloc (strlen (converted) + 1);
+ char *q = escaped;
+ for (const char *p = converted; *p; ++p, ++q)
+ {
+ if (*p == '&')
+ {
+ if (*(p+1) == '&')
+ {
+ *q = '&';
+ ++p;
+ }
+ else
+ {
+ *q = '_';
+ }
+ }
+ else
+ {
+ *q = *p;
+ }
+ }
+
+ /* Null termination */
+ *q = '\0';
+
+ g_free (converted);
+
+ return escaped;
+}
+
+/* FIXME: needs THREADSAFE? */
+#if HAVE_NSINONBLOCKINGALERTSERVICE_H
+NS_IMPL_ISUPPORTS2 (GeckoPromptService,
+ nsIPromptService,
+ nsINonBlockingAlertService)
+#else
+NS_IMPL_ISUPPORTS1 (GeckoPromptService,
+ nsIPromptService)
+#endif
+
+GeckoPromptService::GeckoPromptService()
+{
+}
+
+GeckoPromptService::~GeckoPromptService()
+{
+}
+
+/* nsIPromptService implementation */
+
+/* void alert (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText); */
+NS_IMETHODIMP
+GeckoPromptService::Alert (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText)
+{
+ Prompter prompt (GTK_STOCK_DIALOG_INFO, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.Run ();
+
+ return NS_OK;
+}
+
+/* void alertCheck (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+GeckoPromptService::AlertCheck (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState)
+{
+ Prompter prompt (GTK_STOCK_DIALOG_INFO, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ prompt.Run ();
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* boolean confirm (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText); */
+NS_IMETHODIMP
+GeckoPromptService::Confirm (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+
+ Prompter prompt (GTK_STOCK_DIALOG_QUESTION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.Run (_retval);
+
+ return NS_OK;
+}
+
+/* boolean confirmCheck (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+GeckoPromptService::ConfirmCheck (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+
+ Prompter prompt (GTK_STOCK_DIALOG_QUESTION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ prompt.Run (_retval);
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* PRInt32 confirmEx (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, in unsigned long aButtonFlags, in wstring aButton0Title, in wstring aButton1Title, in wstring aButton2Title, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+GeckoPromptService::ConfirmEx (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRUint32 aButtonFlags,
+ const PRUnichar *aButton0Title,
+ const PRUnichar *aButton1Title,
+ const PRUnichar *aButton2Title,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState,
+ PRInt32 *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+
+ Prompter prompt (GTK_STOCK_DIALOG_QUESTION, aParent, aDialogTitle, aText);
+ prompt.AddButtonsWithFlags (aButtonFlags, aButton0Title,
+ aButton1Title, aButton2Title);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ *_retval = prompt.Run (nsnull);
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* boolean prompt (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, inout wstring aValue, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+GeckoPromptService::Prompt (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRUnichar **aValue,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+ NS_ENSURE_ARG_POINTER (aValue);
+
+ Prompter prompt (GTK_STOCK_DIALOG_QUESTION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddEntry (nsnull, *aValue, PR_FALSE);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ prompt.Run (_retval);
+ prompt.GetText (0, aValue);
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* boolean promptUsernameAndPassword (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, inout wstring aUsername, inout wstring aPassword, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+GeckoPromptService::PromptUsernameAndPassword (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRUnichar **aUsername,
+ PRUnichar **aPassword,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+ NS_ENSURE_ARG_POINTER (aUsername);
+ NS_ENSURE_ARG_POINTER (aPassword);
+
+ Prompter prompt (GTK_STOCK_DIALOG_AUTHENTICATION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddEntry (_("_Username:"), *aUsername, PR_FALSE);
+ prompt.AddEntry (_("_Password:"), *aPassword, PR_TRUE);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ prompt.Run (_retval);
+ prompt.GetText (0, aUsername);
+ prompt.GetText (1, aPassword);
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* boolean promptPassword (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, inout wstring aPassword, in wstring aCheckMsg, inout boolean aCheckState); */
+NS_IMETHODIMP
+GeckoPromptService::PromptPassword (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRUnichar **aPassword,
+ const PRUnichar *aCheckMsg,
+ PRBool *aCheckState,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+ NS_ENSURE_ARG_POINTER (aPassword);
+
+ Prompter prompt (GTK_STOCK_DIALOG_AUTHENTICATION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddEntry (_("_Password:"), *aPassword, PR_TRUE);
+ prompt.AddCheckbox (aCheckMsg, aCheckState);
+
+ // FIXME: Add a CAPSLOCK indicator?
+
+ prompt.Run (_retval);
+ prompt.GetText (0, aPassword);
+ prompt.GetCheckboxState (aCheckState);
+
+ return NS_OK;
+}
+
+/* boolean select (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, in PRUint32 aCount, [array, size_is (aCount)] in wstring aSelectList, out long aOutSelection); */
+NS_IMETHODIMP
+GeckoPromptService::Select (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText,
+ PRUint32 aCount,
+ const PRUnichar **aSelectList,
+ PRInt32 *aOutSelection,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER (_retval);
+ NS_ENSURE_ARG_POINTER (aOutSelection);
+
+ Prompter prompt (GTK_STOCK_DIALOG_QUESTION, aParent, aDialogTitle, aText);
+ prompt.AddStockButton (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ prompt.AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt.AddSelect (aCount, aSelectList, *aOutSelection);
+
+ prompt.Run (_retval);
+ prompt.GetSelected (aOutSelection);
+
+ return NS_OK;
+}
+
+#if HAVE_NSINONBLOCKINGALERTSERVICE_H
+
+/* showNonBlockingAlert (in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText); */
+NS_IMETHODIMP
+GeckoPromptService::ShowNonBlockingAlert (nsIDOMWindow *aParent,
+ const PRUnichar *aDialogTitle,
+ const PRUnichar *aText)
+{
+ Prompter *prompt = new Prompter (GTK_STOCK_DIALOG_INFO, aParent, aDialogTitle, aText);
+ if (!prompt) return NS_ERROR_OUT_OF_MEMORY;
+
+ prompt->AddStockButton (GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ prompt->Show ();
+
+ return NS_OK;
+}
+
+#endif /* HAVE_NSINONBLOCKINGALERTSERVICE_H */
diff --git a/embed/xulrunner/src/GeckoPromptService.h b/embed/xulrunner/src/GeckoPromptService.h
new file mode 100644
index 000000000..b2ef610b8
--- /dev/null
+++ b/embed/xulrunner/src/GeckoPromptService.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2005, 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#ifndef GECKO_PROMPT_SERVICE_H
+#define GECKO_PROMPT_SERVICE_H
+
+#include <nsIPromptService.h>
+
+#if HAVE_NSINONBLOCKINGALERTSERVICE_H
+#include <nsINonBlockingAlertService.h>
+#endif
+
+#define GECKO_PROMPT_SERVICE_CID \
+{ /* cadc6035-7c53-4039-823b-004a289d5eb2 */ \
+ 0xcadc6035, 0x7c53, 0x4039, \
+ { 0x82, 0x3b, 0x00, 0x4a, 0x28, 0x9d, 0x5e, 0xb2 } }
+
+#define GECKO_PROMPT_SERVICE_CLASSNAME "Gecko Prompt Service"
+
+class GeckoPromptService : public nsIPromptService
+#if HAVE_NSINONBLOCKINGALERTSERVICE_H
+ , public nsINonBlockingAlertService
+#endif
+{
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROMPTSERVICE
+#if HAVE_NSINONBLOCKINGALERTSERVICE_H
+ NS_DECL_NSINONBLOCKINGALERTSERVICE
+#endif
+
+ GeckoPromptService();
+ virtual ~GeckoPromptService();
+};
+
+#endif /* GECKO_PROMPT_SERVICE_H */
diff --git a/embed/xulrunner/src/GeckoSingle.cpp b/embed/xulrunner/src/GeckoSingle.cpp
new file mode 100644
index 000000000..4b5d8e467
--- /dev/null
+++ b/embed/xulrunner/src/GeckoSingle.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include <config.h>
+
+#include <stdlib.h>
+#include "nsIDocShell.h"
+#include "nsIWebProgress.h"
+#include "nsIWebBrowserStream.h"
+#include "nsIWidget.h"
+
+// all of our local includes
+#include "GeckoSingle.h"
+#include "EmbedWindow.h"
+#include "gecko-init.h"
+#include "gecko-init-private.h"
+
+GSList *GeckoSingle::sWindowList = nsnull;
+PRUint32 GeckoSingle::sWidgetCount = 0;
+
+GeckoSingle::GeckoSingle()
+{
+}
+
+GeckoSingle::~GeckoSingle()
+{
+}
+
+/* static */
+GeckoBrowser *
+GeckoSingle::FindPrivateForBrowser(nsIWebBrowserChrome *aBrowser)
+{
+ // This function doesn't get called very often at all ( only when
+ // creating a new window ) so it's OK to walk the list of open
+ // windows.
+ for (GSList *l = sWindowList; l != NULL; l = l->next) {
+ GeckoBrowser *tmpPrivate = static_cast<GeckoBrowser *>(l->data);
+ // get the browser object for that window
+ nsIWebBrowserChrome *chrome = static_cast<nsIWebBrowserChrome *>
+ (tmpPrivate->mWindow);
+ if (chrome == aBrowser)
+ return tmpPrivate;
+ }
+
+ return nsnull;
+}
+
+/* static */
+void
+GeckoSingle::ReparentToOffscreen (GtkWidget* aWidget)
+{
+ gecko_reparent_to_offscreen (aWidget);
+}
+
+/* static */
+void
+GeckoSingle::AddBrowser(GeckoBrowser *aBrowser)
+{
+ PushStartup();
+ sWindowList = g_slist_prepend (sWindowList, aBrowser);
+}
+
+/* static */
+void
+GeckoSingle::RemoveBrowser(GeckoBrowser *aBrowser)
+{
+ sWindowList = g_slist_remove (sWindowList, aBrowser);
+ PopStartup();
+}
+
+/* static */
+void
+GeckoSingle::PushStartup()
+{
+ GeckoSingle::sWidgetCount++;
+}
+
+/* static */
+void
+GeckoSingle::PopStartup()
+{
+ GeckoSingle::sWidgetCount--;
+ if (GeckoSingle::sWidgetCount == 0) {
+ gecko_shutdown();
+#ifdef XPCOM_GLUE
+ XPCOMGlueShutdown();
+#endif
+ }
+}
diff --git a/embed/xulrunner/src/GeckoSingle.h b/embed/xulrunner/src/GeckoSingle.h
new file mode 100644
index 000000000..7654d9a9d
--- /dev/null
+++ b/embed/xulrunner/src/GeckoSingle.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef __GeckoSingle_h
+#define __GeckoSingle_h
+
+#include <nsCOMPtr.h>
+#include <nsEmbedString.h>
+#include <nsIWebNavigation.h>
+#include <nsISHistory.h>
+// for our one function that gets the GeckoSingle via the chrome
+// object.
+#include <nsIWebBrowserChrome.h>
+#include <nsIAppShell.h>
+// app component registration
+#include <nsIGenericFactory.h>
+#include <nsIComponentRegistrar.h>
+
+#include "gecko-embed-single.h"
+#include "gecko-embed.h"
+
+#include "GeckoBrowser.h"
+
+class EmbedProfile;
+class EmbedProgress;
+class EmbedWindow;
+class EmbedContentListener;
+class EmbedEventListener;
+
+class nsPIDOMWindow;
+class nsIDirectoryServiceProvider;
+class nsProfileDirServiceProvider;
+
+class GeckoSingle
+{
+ friend class GeckoBrowser;
+
+ public:
+
+ GeckoSingle();
+ ~GeckoSingle();
+
+ static void PushStartup ();
+ static void PopStartup ();
+
+ // static GeckoSingle* GetInstance();
+
+ // This function will find the specific GeckoBrowser object for a
+ // given nsIWebBrowserChrome.
+ static GeckoBrowser *FindPrivateForBrowser(nsIWebBrowserChrome *aBrowser);
+
+ // the number of widgets that have been created
+ static PRUint32 sWidgetCount;
+ // the list of application-specific components to register
+ static const nsModuleComponentInfo *sAppComps;
+ static int sNumAppComps;
+ // the list of all open windows
+ static GSList *sWindowList;
+
+ static void ReparentToOffscreen (GtkWidget *aWidget);
+ static void AddBrowser (GeckoBrowser *aBrowser);
+ static void RemoveBrowser (GeckoBrowser *aBrowser);
+};
+
+#endif /* __GeckoSingle_h */
diff --git a/embed/xulrunner/src/GeckoUtils.cpp b/embed/xulrunner/src/GeckoUtils.cpp
new file mode 100644
index 000000000..b9d6e3f53
--- /dev/null
+++ b/embed/xulrunner/src/GeckoUtils.cpp
@@ -0,0 +1,87 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright © 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brian Ryner <bryner@brianryner.com>
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include "GeckoUtils.h"
+
+#include "gecko-embed.h"
+
+#include <nsCOMPtr.h>
+#include <nsIDOMWindow.h>
+#include <nsIWindowWatcher.h>
+#include <nsIWebBrowserChrome.h>
+#include <nsIEmbeddingSiteWindow.h>
+#include <nsIServiceManager.h>
+#include <nsServiceManagerUtils.h>
+
+GtkWidget *
+GeckoUtils::GetGeckoEmbedForDOMWindow (nsIDOMWindow * aDOMWindow)
+{
+ if (!aDOMWindow)
+ return NULL;
+
+ /* Get the toplevel DOM window, in case this window is a frame */
+ nsCOMPtr<nsIDOMWindow> domWin;
+ aDOMWindow->GetTop (getter_AddRefs (domWin));
+ if (!domWin)
+ return NULL;
+
+ nsCOMPtr< nsIWindowWatcher> wwatch
+ (do_GetService ("@mozilla.org/embedcomp/window-watcher;1"));
+ NS_ENSURE_TRUE (wwatch, NULL);
+
+ nsCOMPtr<nsIWebBrowserChrome> chrome;
+ wwatch->GetChromeForWindow (domWin, getter_AddRefs (chrome));
+
+ nsCOMPtr <nsIEmbeddingSiteWindow> siteWindow (do_QueryInterface (chrome));
+ if (!siteWindow)
+ return NULL;
+
+ GtkWidget *widget;
+ siteWindow->GetSiteWindow ((void **) &widget);
+ if (!widget || !GECKO_IS_EMBED (widget))
+ return NULL;
+
+ return widget;
+}
+
+GtkWidget *
+GeckoUtils::GetGtkWindowForDOMWindow (nsIDOMWindow * aDOMWindow)
+{
+ GtkWidget *embed = GeckoUtils::GetGeckoEmbedForDOMWindow (aDOMWindow);
+ if (!embed)
+ return NULL;
+
+ GtkWidget *gtkWin = gtk_widget_get_toplevel (embed);
+ if (!GTK_WIDGET_TOPLEVEL (gtkWin))
+ return NULL;
+
+ return gtkWin;
+}
diff --git a/embed/xulrunner/src/GeckoUtils.h b/embed/xulrunner/src/GeckoUtils.h
new file mode 100644
index 000000000..05012e6b2
--- /dev/null
+++ b/embed/xulrunner/src/GeckoUtils.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#ifndef GECKO_UTILS_H
+#define GECKO_UTILS_H
+
+#include <gtk/gtkwidget.h>
+
+class nsIDOMWindow;
+
+namespace GeckoUtils
+{
+ GtkWidget* GetGeckoEmbedForDOMWindow (nsIDOMWindow*);
+ GtkWidget* GetGtkWindowForDOMWindow (nsIDOMWindow*);
+}
+
+#endif
diff --git a/embed/xulrunner/src/Makefile.am b/embed/xulrunner/src/Makefile.am
new file mode 100644
index 000000000..a3afed257
--- /dev/null
+++ b/embed/xulrunner/src/Makefile.am
@@ -0,0 +1,167 @@
+NULL =
+
+required = \
+ . \
+ accessibility \
+ content \
+ embedcomponents \
+ docshell \
+ dom \
+ embed_base \
+ gfx \
+ intl \
+ js \
+ layout \
+ necko \
+ profdirserviceprovider \
+ shistory \
+ string \
+ uriloader \
+ webbrwsr \
+ webshell \
+ widget \
+ windowwatcher \
+ xpcom \
+ xpconnect \
+ xulapp \
+ $(NULL)
+
+MARSHALERS = gecko-embed-marshal.h gecko-embed-marshal.cpp
+TYPES_SOURCES = gecko-embed-type-builtins.h gecko-embed-type-builtins.cpp
+
+BUILT_SOURCES= $(MARSHALERS) $(TYPES_SOURCES)
+
+gecko-embed-marshal.cpp: gecko-embed-marshal.list
+ $(GLIB_GENMARSHAL) --prefix=gecko_embed_marshal $< --header --body > $@
+
+gecko-embed-marshal.h: gecko-embed-marshal.list
+ $(GLIB_GENMARSHAL) --prefix=gecko_embed_marshal $< --header > $@
+
+TYPES_H_FILES = \
+ gecko-embed-types.h \
+ $(NULL)
+
+stamp_files = \
+ stamp-gecko-embed-type-builtins.cpp \
+ stamp-gecko-embed-type-builtins.h \
+ $(NULL)
+
+gecko-embed-type-builtins.cpp: stamp-gecko-embed-type-builtins.cpp Makefile
+ @true
+stamp-gecko-embed-type-builtins.cpp: Makefile $(TYPES_H_FILES)
+ $(GLIB_MKENUMS) \
+ --fhead "#include \"gecko-embed-type-builtins.h\"\n\n" \
+ --fprod "\n/* enumerations from \"@filename@\" */" \
+ --fprod "\n#include \"@filename@\"" \
+ --vhead "GType\n@enum_name@_get_type (void)\n{\n" \
+ --vhead " static GType type = 0;\n\n" \
+ --vhead " if (G_UNLIKELY (type == 0))\n {\n" \
+ --vhead " static const G@Type@Value _@enum_name@_values[] = {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n };\n\n" \
+ --vtail " type = g_@type@_register_static (\"@EnumName@\", _@enum_name@_values);\n }\n\n" \
+ --vtail " return type;\n}\n\n" \
+ $(filter-out $<,$^) > xgen-$(@F) \
+ && ( cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%) ) \
+ && rm -f xgen-$(@F) \
+ && echo timestamp > $(@F)
+
+gecko-embed-type-builtins.h: stamp-gecko-embed-type-builtins.h Makefile
+ @true
+stamp-gecko-embed-type-builtins.h: Makefile $(TYPES_H_FILES)
+ $(GLIB_MKENUMS) \
+ --fhead "#ifndef GECKO_TYPE_BUILTINS_H\n" \
+ --fhead "#define GECKO_TYPE_BUILTINS_H 1\n\n" \
+ --fhead "#include <glib-object.h>\n\n" \
+ --fhead "G_BEGIN_DECLS\n\n" \
+ --ftail "G_END_DECLS\n\n" \
+ --ftail "#endif /* GECKO_TYPE_BUILTINS_H */\n" \
+ --fprod "\n/* --- @filename@ --- */" \
+ --eprod "#define GECKO_TYPE_@ENUMSHORT@ @enum_name@_get_type()\n" \
+ --eprod "GType @enum_name@_get_type (void);\n" \
+ $(filter-out $<,$^) > xgen-$(@F) \
+ && ( cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%) ) \
+ && rm -f xgen-$(@F) \
+ && echo timestamp > $(@F)
+
+lib_LTLIBRARIES = libgnomegeckoembed-0.0.la
+
+libgnomegeckoembed_0_0_la_SOURCES = \
+ $(MARSHALERS) \
+ $(TYPES_SOURCES) \
+ gecko-dom-event.cpp \
+ gecko-dom-event.h \
+ gecko-dom-event-internal.h \
+ gecko-dom-event-private.h \
+ gecko-embed.cpp \
+ gecko-embed.h \
+ gecko-embed-private.h \
+ gecko-embed-signals.h \
+ gecko-embed-single.cpp \
+ gecko-embed-single.h \
+ gecko-embed-single-private.h \
+ gecko-embed-types.h \
+ gecko-init.cpp \
+ gecko-init.h \
+ gecko-init-internal.h \
+ gecko-init-private.h \
+ AutoJSContextStack.cpp \
+ AutoJSContextStack.h \
+ AutoWindowModalState.cpp \
+ AutoWindowModalState.h \
+ EmbedContentListener.cpp \
+ EmbedContentListener.h \
+ EmbedEventListener.cpp \
+ EmbedEventListener.h \
+ EmbedProgress.cpp \
+ EmbedProgress.h \
+ EmbedWindow.cpp \
+ EmbedWindowCreator.cpp \
+ EmbedWindowCreator.h \
+ EmbedWindow.h \
+ GeckoBrowser.cpp \
+ GeckoBrowser.h \
+ GeckoPromptService.cpp \
+ GeckoPromptService.h \
+ GeckoSingle.cpp \
+ GeckoSingle.h \
+ GeckoUtils.cpp \
+ GeckoUtils.h \
+ $(NULL)
+
+libgnomegeckoembed_0_0_la_CPPFLAGS = \
+ $(addprefix -I$(GECKO_INCLUDE_ROOT)/,$(required)) \
+ $(AM_CPPFLAGS)
+
+# -DDEBUG \
+# -DXPCOM_GLUE
+#-DMOZILLA_STRICT_API
+
+libgnomegeckoembed_0_0_la_CXXFLAGS = \
+ $(GGE_DEPENDENCY_CFLAGS) \
+ $(GECKO_CFLAGS) \
+ $(AM_CXXFLAGS)
+
+libgnomegeckoembed_0_0_la_LIBADD = \
+ $(GGE_DEPENDENCY_LIBS) \
+ $(GECKO_LIBS) \
+ $(GECKO_EXTRA_LIBS) \
+ $(GECKO_GLUE_LIBS)
+
+libgnomegeckoembed_0_0_la_LDFLAGS = \
+ $(AM_LDFLAGS)
+
+gnomegeckoembedincludedir = $(includedir)/gnome-gecko-embed-0.0
+gnomegeckoembedinclude_HEADERS =
+
+gnomegeckoembedsubincludedir = $(includedir)/gnome-gecko-embed-0.0/gecko-embed
+gnomegeckoembedsubinclude_HEADERS =
+
+CLEANFILES = \
+ $(stamp_files) \
+ $(BUILT_SOURCES) \
+ $(NULL)
+
+EXTRA_DIST = \
+ gecko-embed-marshal.list \
+ $(NULL)
diff --git a/embed/xulrunner/src/gecko-dom-event-internal.h b/embed/xulrunner/src/gecko-dom-event-internal.h
new file mode 100644
index 000000000..2d0309bd9
--- /dev/null
+++ b/embed/xulrunner/src/gecko-dom-event-internal.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#ifndef GECKO_DOM_EVENT_INTERNAL_H
+#define GECKO_DOM_EVENT_INTERNAL_H
+
+class nsIDOMEvent;
+
+nsIDOMEvent * gecko_dom_event_get_I (GeckoDOMEvent *);
+
+#endif
diff --git a/embed/xulrunner/src/gecko-dom-event-private.h b/embed/xulrunner/src/gecko-dom-event-private.h
new file mode 100644
index 000000000..995f8cec0
--- /dev/null
+++ b/embed/xulrunner/src/gecko-dom-event-private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#ifndef GECKO_DOM_EVENT_PRIVATE_H
+#define GECKO_DOM_EVENT_PRIVATE_H
+
+struct _GeckoDOMEvent {
+ nsIDOMEvent *mEvent;
+};
+
+class nsIDOMEvent;
+
+#define GECKO_DOM_EVENT_STATIC_INIT(aEvent,aDOMEvent) \
+{ aEvent.mEvent = aDOMEvent; }
+
+#define GECKO_DOM_EVENT_STATIC_DEINIT(aEvent) \
+{ }
+
+GeckoDOMEvent *gecko_dom_event_new (nsIDOMEvent *);
+
+#endif
diff --git a/embed/xulrunner/src/gecko-dom-event.cpp b/embed/xulrunner/src/gecko-dom-event.cpp
new file mode 100644
index 000000000..2acdac583
--- /dev/null
+++ b/embed/xulrunner/src/gecko-dom-event.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include "gecko-dom-event.h"
+#include "gecko-dom-event-internal.h"
+#include "gecko-dom-event-private.h"
+
+#include <nsIDOMEvent.h>
+
+/* GType implementation */
+
+GType
+gecko_dom_event_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ type = g_boxed_type_register_static
+ ("GeckoDOMEvent",
+ (GBoxedCopyFunc) gecko_dom_event_copy,
+ (GBoxedFreeFunc) gecko_dom_event_free);
+ }
+
+ return type;
+}
+
+/* Public API */
+
+GeckoDOMEvent *
+gecko_dom_event_new (nsIDOMEvent *aEvent)
+{
+ /* FIXME use slice alloc */
+ GeckoDOMEvent *event = g_new (GeckoDOMEvent, 1);
+
+ NS_ADDREF (event->mEvent = aEvent);
+
+ return event;
+}
+
+GeckoDOMEvent *
+gecko_dom_event_copy (GeckoDOMEvent *aEvent)
+{
+ return gecko_dom_event_new (aEvent->mEvent);
+}
+
+void
+gecko_dom_event_free (GeckoDOMEvent *aEvent)
+{
+ NS_RELEASE (aEvent->mEvent);
+ /* FIXME slice alloc */
+ g_free (aEvent);
+}
+
+nsIDOMEvent *
+gecko_dom_event_get_I (GeckoDOMEvent *aEvent)
+{
+ return aEvent->mEvent;
+}
diff --git a/embed/xulrunner/src/gecko-dom-event.h b/embed/xulrunner/src/gecko-dom-event.h
new file mode 100644
index 000000000..ee1a40768
--- /dev/null
+++ b/embed/xulrunner/src/gecko-dom-event.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#ifndef GECKO_DOM_EVENT_H
+#define GECKO_DOM_EVENT_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GECKO_TYPE_DOM_EVENT (gecko_dom_event_get_type ())
+
+typedef struct _GeckoDOMEvent GeckoDOMEvent;
+
+GType gecko_dom_event_get_type (void);
+
+GeckoDOMEvent * gecko_dom_event_copy (GeckoDOMEvent *);
+
+void gecko_dom_event_free (GeckoDOMEvent *);
+
+G_END_DECLS
+
+#endif
diff --git a/embed/xulrunner/src/gecko-embed-marshal.list b/embed/xulrunner/src/gecko-embed-marshal.list
new file mode 100644
index 000000000..f32b027a6
--- /dev/null
+++ b/embed/xulrunner/src/gecko-embed-marshal.list
@@ -0,0 +1,10 @@
+BOOLEAN:BOXED
+BOOLEAN:POINTER
+BOOLEAN:STRING
+VOID:INT,INT
+VOID:INT,UINT
+VOID:OBJECT,UINT
+VOID:POINTER,INT,POINTER
+VOID:POINTER,UINT
+VOID:STRING,INT,INT
+VOID:STRING,INT,UINT
diff --git a/embed/xulrunner/src/gecko-embed-private.h b/embed/xulrunner/src/gecko-embed-private.h
new file mode 100644
index 000000000..8f3fcae09
--- /dev/null
+++ b/embed/xulrunner/src/gecko-embed-private.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef gecko_embed_private_h
+#define gecko_embed_private_h
+
+#include "gecko-embed.h"
+
+class nsIWebBrowser;
+class GeckoBrowser;
+
+G_BEGIN_DECLS
+
+extern void gecko_embed_get_nsIWebBrowser (GeckoEmbed *embed,
+ nsIWebBrowser **retval);
+
+extern GeckoBrowser* gecko_embed_get_GeckoBrowser (GeckoEmbed *embed);
+
+
+G_END_DECLS
+
+#endif /* gecko_embed_private_h */
diff --git a/embed/xulrunner/src/gecko-embed-signals.h b/embed/xulrunner/src/gecko-embed-signals.h
new file mode 100644
index 000000000..d5d67b351
--- /dev/null
+++ b/embed/xulrunner/src/gecko-embed-signals.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef gecko_embed_signals_h
+#define gecko_embed_signals_h
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ DOM_KEY_DOWN,
+ DOM_KEY_PRESS,
+ DOM_KEY_UP,
+ DOM_MOUSE_DOWN,
+ DOM_MOUSE_UP,
+ DOM_MOUSE_CLICK,
+ DOM_MOUSE_DOUBLE_CLICK,
+ DOM_MOUSE_OVER,
+ DOM_MOUSE_OUT,
+ DOM_ACTIVATE,
+ DOM_FOCUS_IN,
+ DOM_FOCUS_OUT,
+ DOM_CONTEXT_MENU,
+
+ LINK_MESSAGE,
+ JS_STATUS,
+ LOCATION,
+ TITLE,
+ PROGRESS,
+ PROGRESS_ALL,
+ NET_STATE,
+ NET_STATE_ALL,
+ NET_START,
+ NET_STOP,
+ NEW_WINDOW,
+ VISIBILITY,
+ DESTROY_BROWSER,
+ OPEN_URI,
+ SIZE_TO,
+ SECURITY_CHANGE,
+ STATUS_CHANGE,
+ LAST_EMBED_SIGNAL
+} GeckoEmbedSignals;
+
+extern guint gecko_embed_signals[LAST_EMBED_SIGNAL];
+
+G_END_DECLS
+
+#endif /* gecko_embed_signals_h */
diff --git a/embed/xulrunner/src/gecko-embed-single-private.h b/embed/xulrunner/src/gecko-embed-single-private.h
new file mode 100644
index 000000000..df2202da3
--- /dev/null
+++ b/embed/xulrunner/src/gecko-embed-single-private.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef gecko_embed_single_private_h
+#define gecko_embed_single_private_h
+
+#include "gecko-embed-single.h"
+
+class GeckoSingle;
+class nsIDirectoryServiceProvider;
+struct nsModuleComponentInfo;
+
+G_BEGIN_DECLS
+
+extern GeckoSingle* gecko_embed_single_get_GeckoSingle (void);
+
+extern void gecko_embed_single_set_directory_service_provider (nsIDirectoryServiceProvider *aProvider);
+
+extern void gecko_embed_single_set_app_components (const nsModuleComponentInfo *aComps,
+ int aNumComps);
+
+extern void gecko_embed_single_create_window (GeckoEmbed **aNewEmbed,
+ guint aChromeFlags);
+
+G_END_DECLS
+
+#endif /* gecko_embed_single_private_h */
diff --git a/embed/xulrunner/src/gecko-embed-single.cpp b/embed/xulrunner/src/gecko-embed-single.cpp
new file mode 100644
index 000000000..dd147e512
--- /dev/null
+++ b/embed/xulrunner/src/gecko-embed-single.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © Ramiro Estrugo
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * Ramiro Estrugo <ramiro@eazel.com>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include "gecko-embed-single.h"
+#include "gecko-embed-private.h"
+#include "gecko-embed-signals.h"
+#include "gecko-embed-marshal.h"
+
+#include "GeckoSingle.h"
+
+#define GECKO_EMBED_SINGLE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GECKO_TYPE_EMBED_SINGLE, GeckoEmbedSinglePrivate))
+
+struct _GeckoEmbedSinglePrivate
+{
+ GeckoSingle *single;
+};
+
+enum
+{
+ NEW_WINDOW_ORPHAN,
+ LAST_SINGLE_SIGNAL
+};
+
+static guint gecko_embed_single_signals[LAST_SINGLE_SIGNAL] = { 0 };
+
+static void gecko_embed_single_class_init (GeckoEmbedSingleClass *klass);
+static void gecko_embed_single_init (GeckoEmbedSingle *embed);
+
+static GObjectClass *parent_class = NULL;
+
+GType
+gecko_embed_single_get_type(void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ const GTypeInfo info =
+ {
+ sizeof (GeckoEmbedSingleClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) gecko_embed_single_class_init,
+ NULL,
+ NULL, /* class_data */
+ sizeof (GeckoEmbedSingle),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gecko_embed_single_init
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT, "GeckoEmbedSingle",
+ &info, (GTypeFlags) 0);
+ }
+
+ return type;
+}
+
+GeckoEmbedSingle *
+gecko_embed_single_get (void)
+{
+ static GeckoEmbedSingle *single = NULL;
+
+ if (!single)
+ {
+ single = GECKO_EMBED_SINGLE (g_object_new (GECKO_TYPE_EMBED_SINGLE, NULL));
+
+ g_object_add_weak_pointer (G_OBJECT (single), (gpointer *) &single);
+ }
+
+ return single;
+}
+
+extern "C" void
+gecko_embed_single_create_window (GeckoEmbed **aNewEmbed,
+ guint aChromeFlags)
+{
+ GeckoEmbedSingle *single = gecko_embed_single_get ();
+
+ *aNewEmbed = nsnull;
+
+ if (!single)
+ return;
+
+ g_signal_emit (single, gecko_embed_single_signals[NEW_WINDOW_ORPHAN], 0,
+ (void **) aNewEmbed, aChromeFlags);
+}
+
+void
+gecko_embed_single_push_startup(void)
+{
+ GeckoEmbedSingle *single = gecko_embed_single_get ();
+
+ single->priv->single->PushStartup();
+}
+
+void
+gecko_embed_single_pop_startup(void)
+{
+ GeckoEmbedSingle *single = gecko_embed_single_get ();
+
+ single->priv->single->PopStartup();
+}
+
+static void
+gecko_embed_single_init(GeckoEmbedSingle *embed)
+{
+ embed->priv = GECKO_EMBED_SINGLE_GET_PRIVATE (embed);
+
+ embed->priv->single = new GeckoSingle ();
+}
+
+static void
+gecko_embed_single_finalize (GObject *object)
+{
+ GeckoEmbedSingle *single = GECKO_EMBED_SINGLE (object);
+
+ delete single->priv->single;
+ single->priv->single = nsnull;
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gecko_embed_single_class_init (GeckoEmbedSingleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
+
+ object_class->finalize = gecko_embed_single_finalize;
+
+ gecko_embed_single_signals[NEW_WINDOW] =
+ g_signal_new ("new_window_orphan",
+ GECKO_TYPE_EMBED_SINGLE,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GeckoEmbedSingleClass, new_window_orphan),
+ NULL, NULL,
+ gecko_embed_marshal_VOID__OBJECT_UINT,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_OBJECT,
+ G_TYPE_UINT);
+
+ g_type_class_add_private (object_class, sizeof (GeckoEmbedSinglePrivate));
+}
diff --git a/embed/xulrunner/src/gecko-embed-single.h b/embed/xulrunner/src/gecko-embed-single.h
new file mode 100644
index 000000000..66554f68b
--- /dev/null
+++ b/embed/xulrunner/src/gecko-embed-single.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © Ramiro Estrugo
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * Ramiro Estrugo <ramiro@eazel.com>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef gecko_embed_single_h
+#define gecko_embed_single_h
+
+#include "gecko-embed-type-builtins.h"
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GECKO_TYPE_EMBED_SINGLE (gecko_embed_single_get_type())
+#define GECKO_EMBED_SINGLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GECKO_TYPE_EMBED_SINGLE, GeckoEmbedSingle))
+#define GECKO_EMBED_SINGLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GECKO_TYPE_EMBED_SINGLE, GeckoEmbedSingleClass))
+#define GECKO_IS_EMBED_SINGLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GECKO_TYPE_EMBED_SINGLE))
+#define GECKO_IS_EMBED_SINGLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GECKO_TYPE_EMBED_SINGLE))
+#define GECKO_EMBED_SINGLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GECKO_TYPE_EMBED_SINGLE, GeckoEmbedSingleClass))
+
+typedef struct _GeckoEmbedSingle GeckoEmbedSingle;
+typedef struct _GeckoEmbedSinglePrivate GeckoEmbedSinglePrivate;
+typedef struct _GeckoEmbedSingleClass GeckoEmbedSingleClass;
+
+/* circular dependency */
+#include "gecko-embed.h"
+
+struct _GeckoEmbedSingle
+{
+ GObject parent_instance;
+
+ /*< private >*/
+ GeckoEmbedSinglePrivate *priv;
+};
+
+struct _GeckoEmbedSingleClass
+{
+ GObjectClass parent_class;
+
+ void (* new_window_orphan) (GeckoEmbedSingle *single,
+ GeckoEmbed **newEmbed,
+ guint chromemask);
+};
+
+GType gecko_embed_single_get_type (void);
+
+GeckoEmbedSingle *gecko_embed_single_get (void);
+
+void gecko_embed_single_push_startup (void);
+
+void gecko_embed_single_pop_startup (void);
+
+
+G_END_DECLS
+
+#endif /* gecko_embed_single_h */
diff --git a/embed/xulrunner/src/gecko-embed-types.h b/embed/xulrunner/src/gecko-embed-types.h
new file mode 100644
index 000000000..c0cb1b71e
--- /dev/null
+++ b/embed/xulrunner/src/gecko-embed-types.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * Ramiro Estrugo <ramiro@eazel.com>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef __GECKO_EMBED_TYPES_H__
+#define __GECKO_EMBED_TYPES_H__
+
+#include <glib-object.h>
+#include "gecko-embed-type-builtins.h"
+
+G_BEGIN_DECLS
+
+/* These are straight out of nsIWebProgressListener.h */
+
+typedef enum
+{
+ GECKO_EMBED_FLAG_START = 1U << 0,
+ GECKO_EMBED_FLAG_REDIRECTING = 1U << 1,
+ GECKO_EMBED_FLAG_TRANSFERRING = 1U << 2,
+ GECKO_EMBED_FLAG_NEGOTIATING = 1U << 3,
+ GECKO_EMBED_FLAG_STOP = 1U << 4,
+
+ GECKO_EMBED_FLAG_IS_REQUEST = 1U << 16,
+ GECKO_EMBED_FLAG_IS_DOCUMENT = 1U << 17,
+ GECKO_EMBED_FLAG_IS_NETWORK = 1U << 18,
+ GECKO_EMBED_FLAG_IS_WINDOW = 1U << 19,
+
+ GECKO_EMBED_FLAG_RESTORING = 1U << 24,
+} GeckoEmbedProgressFlags;
+
+/* These are from various networking headers */
+
+typedef enum
+{
+ /* NS_ERROR_UNKNOWN_HOST */
+ GECKO_EMBED_STATUS_FAILED_DNS = 2152398878U,
+ /* NS_ERROR_CONNECTION_REFUSED */
+ GECKO_EMBED_STATUS_FAILED_CONNECT = 2152398861U,
+ /* NS_ERROR_NET_TIMEOUT */
+ GECKO_EMBED_STATUS_FAILED_TIMEOUT = 2152398862U,
+ /* NS_BINDING_ABORTED */
+ GECKO_EMBED_STATUS_FAILED_USERCANCELED = 2152398850U
+} GeckoEmbedStatusEnum;
+
+/* These used to be straight out of nsIWebNavigation.h until the API
+ changed. Now there's a mapping table that maps these values to the
+ internal values. */
+
+typedef enum
+{
+ GECKO_EMBED_FLAG_RELOADNORMAL = 0,
+ GECKO_EMBED_FLAG_RELOADBYPASSCACHE = 1,
+ GECKO_EMBED_FLAG_RELOADBYPASSPROXY = 2,
+ GECKO_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE = 3,
+ GECKO_EMBED_FLAG_RELOADCHARSETCHANGE = 4
+} GeckoEmbedReloadFlags;
+
+/* These are straight out of nsIWebBrowserChrome.h */
+
+typedef enum
+{
+ GECKO_EMBED_FLAG_DEFAULTCHROME = 1U << 0,
+ GECKO_EMBED_FLAG_WINDOWBORDERSON = 1U << 1,
+ GECKO_EMBED_FLAG_WINDOWCLOSEON = 1U << 2,
+ GECKO_EMBED_FLAG_WINDOWRESIZEON = 1U << 3,
+ GECKO_EMBED_FLAG_MENUBARON = 1U << 4,
+ GECKO_EMBED_FLAG_TOOLBARON = 1U << 5,
+ GECKO_EMBED_FLAG_LOCATIONBARON = 1U << 6,
+ GECKO_EMBED_FLAG_STATUSBARON = 1U << 7,
+ GECKO_EMBED_FLAG_PERSONALTOOLBARON = 1U << 8,
+ GECKO_EMBED_FLAG_SCROLLBARSON = 1U << 9,
+ GECKO_EMBED_FLAG_TITLEBARON = 1U << 10,
+ GECKO_EMBED_FLAG_EXTRACHROMEON = 1U << 11,
+ GECKO_EMBED_FLAG_ALLCHROME = 1U << 12,
+ GECKO_EMBED_FLAG_WINDOWRAISED = 1U << 25,
+ GECKO_EMBED_FLAG_WINDOWLOWERED = 1U << 26,
+ GECKO_EMBED_FLAG_CENTERSCREEN = 1U << 27,
+ GECKO_EMBED_FLAG_DEPENDENT = 1U << 28,
+ GECKO_EMBED_FLAG_MODAL = 1U << 29,
+ GECKO_EMBED_FLAG_OPENASDIALOG = 1U << 30,
+ GECKO_EMBED_FLAG_OPENASCHROME = 1U << 31,
+} GeckoEmbedChromeFlags;
+
+G_END_DECLS
+
+#endif /* !__GECKO_EMBED_TYPES_H__ */
diff --git a/embed/xulrunner/src/gecko-embed.cpp b/embed/xulrunner/src/gecko-embed.cpp
new file mode 100644
index 000000000..1db324c44
--- /dev/null
+++ b/embed/xulrunner/src/gecko-embed.cpp
@@ -0,0 +1,1029 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © Ramiro Estrugo
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * Ramiro Estrugo <ramiro@eazel.com>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include "config.h"
+
+#include "gecko-embed.h"
+#include "gecko-embed-private.h"
+#include "gecko-embed-signals.h"
+#include "gecko-embed-marshal.h"
+#include "gecko-embed-single.h"
+#include "gecko-embed-types.h"
+
+#include "gecko-dom-event.h"
+
+#include "GeckoBrowser.h"
+#include "EmbedWindow.h"
+
+#ifdef XPCOM_GLUE
+#include "nsXPCOMGlue.h"
+#endif
+
+// so we can do our get_nsIWebBrowser later...
+#include <nsIWebBrowser.h>
+
+#include <stdio.h>
+
+#define GET_OBJECT_CLASS_TYPE(x) G_OBJECT_CLASS_TYPE(x)
+
+class nsIDirectoryServiceProvider;
+
+// class and instance initialization
+
+static void gecko_embed_class_init (GeckoEmbedClass *klass);
+static void gecko_embed_init (GeckoEmbed *embed);
+
+// GtkObject methods
+
+static void gecko_embed_destroy(GtkObject *object);
+
+// GtkWidget methods
+
+static void gecko_embed_realize(GtkWidget *widget);
+
+static void gecko_embed_unrealize(GtkWidget *widget);
+
+static void gecko_embed_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
+
+static void gecko_embed_map(GtkWidget *widget);
+
+static void gecko_embed_unmap(GtkWidget *widget);
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+static AtkObject* gecko_embed_get_accessible (GtkWidget *widget);
+#endif
+
+static gint handle_child_focus_in(GtkWidget *aWidget,
+ GdkEventFocus *aGdkFocusEvent,
+ GeckoEmbed *aEmbed);
+
+static gint handle_child_focus_out(GtkWidget *aWidget,
+ GdkEventFocus *aGdkFocusEvent,
+ GeckoEmbed *aEmbed);
+
+static PRInt32 sWidgetCount;
+
+// globals for this type of widget
+
+static GtkBinClass *parent_class;
+
+guint gecko_embed_signals[LAST_EMBED_SIGNAL] = { 0 };
+
+// GtkObject + class-related functions
+
+#define GECKO_EMBED_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GECKO_TYPE_EMBED, GeckoEmbedPrivate))
+
+struct _GeckoEmbedPrivate
+{
+ GeckoBrowser *browser;
+};
+
+GType
+gecko_embed_get_type(void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ const GTypeInfo info =
+ {
+ sizeof (GeckoEmbedClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) gecko_embed_class_init,
+ NULL,
+ NULL, /* class_data */
+ sizeof (GeckoEmbed),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gecko_embed_init
+ };
+
+ type = g_type_register_static (GTK_TYPE_BIN, "GeckoEmbed",
+ &info, (GTypeFlags) 0);
+ }
+
+ return type;
+}
+
+
+/* GObject methods */
+
+#define GET_BROWSER(x) (((GeckoEmbed *) x)->priv->browser)
+
+// FIXME split in dispose and finalize
+static void
+gecko_embed_destroy(GtkObject *object)
+{
+ GeckoEmbed *embed = GECKO_EMBED (object);
+ GeckoBrowser *browser = GET_BROWSER (object);
+
+ if (browser) {
+
+ // Destroy the widget only if it's been Init()ed.
+ if(browser->mMozWindowWidget != 0) {
+ browser->Destroy();
+ }
+
+ delete browser;
+ embed->priv->browser = NULL;
+ }
+
+ gecko_embed_single_pop_startup();
+}
+
+// GtkWidget methods
+
+static void
+gecko_embed_realize(GtkWidget *widget)
+{
+ GeckoEmbed *embed = GECKO_EMBED (widget);
+ GeckoEmbedPrivate *priv = embed->priv;
+ GeckoBrowser *browser = GET_BROWSER (widget);
+ GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
+ GdkWindowAttr attributes;
+ int attributes_mask;
+
+ GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, embed);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+
+ // initialize the window
+ nsresult rv;
+ rv = browser->Init(embed);
+ g_return_if_fail(NS_SUCCEEDED(rv));
+
+ PRBool alreadyRealized = PR_FALSE;
+ rv = browser->Realize(&alreadyRealized);
+ g_return_if_fail(NS_SUCCEEDED(rv));
+
+ // if we're already realized we don't need to hook up to anything below
+ if (alreadyRealized)
+ return;
+
+ browser->LoadCurrentURI();
+
+ GtkWidget *child_widget = GTK_BIN (widget)->child;
+ g_signal_connect_object (child_widget, "focus_in_event",
+ G_CALLBACK (handle_child_focus_in), embed,
+ (GConnectFlags) 0);
+ g_signal_connect_object (child_widget, "focus_out_event",
+ G_CALLBACK (handle_child_focus_out), embed,
+ (GConnectFlags) 0);
+#if 0
+ // connect to the focus out event for the child
+ gtk_signal_connect_while_alive(GTK_OBJECT(child_widget),
+ "focus_out_event",
+ GTK_SIGNAL_FUNC(handle_child_focus_out),
+ embed,
+ GTK_OBJECT(child_widget));
+ gtk_signal_connect_while_alive(GTK_OBJECT(child_widget),
+ "focus_in_event",
+ GTK_SIGNAL_FUNC(handle_child_focus_in),
+ embed,
+ GTK_OBJECT(child_widget));
+#endif
+}
+
+static void
+gecko_embed_unrealize(GtkWidget *widget)
+{
+ GeckoEmbed *embed = GECKO_EMBED (widget);
+ GeckoEmbedPrivate *priv = embed->priv;
+ GeckoBrowser *browser = GET_BROWSER (widget);
+ GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
+
+ if (browser) {
+ browser->Unrealize();
+ }
+
+ if (GTK_WIDGET_CLASS(parent_class)->unrealize)
+ GTK_WIDGET_CLASS(parent_class)->unrealize (widget);
+}
+
+static void
+gecko_embed_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GeckoEmbed *embed = GECKO_EMBED (widget);
+ GeckoBrowser *browser = GET_BROWSER (widget);
+
+ widget->allocation = *allocation;
+
+ if (GTK_WIDGET_REALIZED(widget))
+ {
+ gdk_window_move_resize(widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ browser->Resize(allocation->width, allocation->height);
+ }
+}
+
+static void
+gecko_embed_map (GtkWidget *widget)
+{
+ GeckoEmbed *embed = GECKO_EMBED (widget);
+ GeckoBrowser *browser = GET_BROWSER (widget);
+
+ GTK_WIDGET_SET_FLAGS(widget, GTK_MAPPED);
+
+ browser->Show();
+
+ gdk_window_show(widget->window);
+
+}
+
+static void
+gecko_embed_unmap (GtkWidget *widget)
+{
+ GeckoEmbed *embed = GECKO_EMBED (widget);
+ GeckoBrowser *browser = GET_BROWSER (widget);
+
+ GTK_WIDGET_UNSET_FLAGS(widget, GTK_MAPPED);
+
+ gdk_window_hide(widget->window);
+
+ browser->Hide();
+}
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+static AtkObject*
+gecko_embed_get_accessible (GtkWidget *widget)
+{
+ GeckoEmbed *embed = GECKO_EMBED (widget);
+ GeckoBrowser *browser = GET_BROWSER (widget);
+
+ return static_cast<AtkObject *>
+ (browser->GetAtkObjectForCurrentDocument());
+}
+#endif /* MOZ_ACCESSIBILITY_ATK */
+
+static gint
+handle_child_focus_in (GtkWidget *aWidget,
+ GdkEventFocus *aGdkFocusEvent,
+ GeckoEmbed *aEmbed)
+{
+ GeckoBrowser *browser = GET_BROWSER (aEmbed);
+
+ browser->ChildFocusIn();
+
+ return FALSE;
+}
+
+static gint
+handle_child_focus_out (GtkWidget *aWidget,
+ GdkEventFocus *aGdkFocusEvent,
+ GeckoEmbed *aEmbed)
+{
+ GeckoBrowser *browser = GET_BROWSER (aEmbed);
+
+ browser->ChildFocusOut();
+
+ return FALSE;
+}
+
+// Widget methods
+
+void
+gecko_embed_load_url (GeckoEmbed *embed,
+ const char *url)
+{
+ GeckoBrowser *browser;
+
+ g_return_if_fail(embed != NULL);
+ g_return_if_fail(GECKO_IS_EMBED(embed));
+
+ browser = GET_BROWSER (embed);
+
+ browser->SetURI(url);
+
+ // If the widget is realized, load the URI. If it isn't then we
+ // will load it later.
+ if (GTK_WIDGET_REALIZED(embed))
+ browser->LoadCurrentURI();
+}
+
+void
+gecko_embed_stop_load (GeckoEmbed *embed)
+{
+ GeckoBrowser *browser;
+
+ g_return_if_fail(GECKO_IS_EMBED(embed));
+
+ browser = GET_BROWSER (embed);
+
+ if (browser->mNavigation)
+ browser->mNavigation->Stop(nsIWebNavigation::STOP_ALL);
+}
+
+gboolean
+gecko_embed_can_go_back (GeckoEmbed *embed)
+{
+ PRBool retval = PR_FALSE;
+ GeckoBrowser *browser;
+
+ g_return_val_if_fail (GECKO_IS_EMBED(embed), FALSE);
+
+ browser = GET_BROWSER (embed);
+
+ if (browser->mNavigation)
+ browser->mNavigation->GetCanGoBack(&retval);
+ return retval;
+}
+
+gboolean
+gecko_embed_can_go_forward (GeckoEmbed *embed)
+{
+ PRBool retval = PR_FALSE;
+ GeckoBrowser *browser;
+
+ g_return_val_if_fail (GECKO_IS_EMBED(embed), FALSE);
+
+ browser = GET_BROWSER (embed);
+
+ if (browser->mNavigation)
+ browser->mNavigation->GetCanGoForward(&retval);
+ return retval;
+}
+
+void
+gecko_embed_go_back (GeckoEmbed *embed)
+{
+ GeckoBrowser *browser;
+
+ g_return_if_fail (GECKO_IS_EMBED(embed));
+
+ browser = GET_BROWSER (embed);
+
+ if (browser->mNavigation)
+ browser->mNavigation->GoBack();
+}
+
+void
+gecko_embed_go_forward (GeckoEmbed *embed)
+{
+ GeckoBrowser *browser;
+
+ g_return_if_fail (GECKO_IS_EMBED(embed));
+
+ browser = GET_BROWSER (embed);
+
+ if (browser->mNavigation)
+ browser->mNavigation->GoForward();
+}
+
+void
+gecko_embed_render_data (GeckoEmbed *embed, const char *data,
+ guint32 len, const char *base_uri,
+ const char *mime_type)
+{
+ GeckoBrowser *browser;
+
+ g_return_if_fail (GECKO_IS_EMBED(embed));
+
+ browser = GET_BROWSER (embed);
+
+#if 0
+ browser->OpenStream(base_uri, mime_type);
+ browser->AppendToStream(data, len);
+ browser->CloseStream();
+#endif
+}
+
+void
+gecko_embed_open_stream (GeckoEmbed *embed, const char *base_uri,
+ const char *mime_type)
+{
+ GeckoBrowser *browser;
+
+ g_return_if_fail (GECKO_IS_EMBED(embed));
+ g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(embed)));
+
+ browser = GET_BROWSER (embed);
+
+#if 0
+ browser->OpenStream(base_uri, mime_type);
+#endif
+}
+
+void gecko_embed_append_data (GeckoEmbed *embed, const char *data,
+ guint32 len)
+{
+ GeckoBrowser *browser;
+
+ g_return_if_fail (GECKO_IS_EMBED(embed));
+ g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(embed)));
+
+ browser = GET_BROWSER (embed);
+#if 0
+ browser->AppendToStream(data, len);
+#endif
+}
+
+void
+gecko_embed_close_stream (GeckoEmbed *embed)
+{
+ GeckoBrowser *browser;
+
+ g_return_if_fail (GECKO_IS_EMBED(embed));
+ g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(embed)));
+
+ browser = GET_BROWSER (embed);
+#if 0
+ browser->CloseStream();
+#endif
+}
+
+char *
+gecko_embed_get_link_message (GeckoEmbed *embed)
+{
+ char *retval = nsnull;
+ GeckoBrowser *browser;
+ nsEmbedCString tmpCString;
+
+ g_return_val_if_fail (GECKO_IS_EMBED(embed), (char *)NULL);
+
+ browser = GET_BROWSER (embed);
+
+ if (browser->mWindow) {
+ NS_UTF16ToCString(browser->mWindow->mLinkMessage,
+ NS_CSTRING_ENCODING_UTF8, tmpCString);
+ retval = g_strdup(tmpCString.get());
+ }
+
+ return retval;
+}
+
+char *
+gecko_embed_get_js_status (GeckoEmbed *embed)
+{
+ char *retval = nsnull;
+ GeckoBrowser *browser;
+ nsEmbedCString tmpCString;
+
+ g_return_val_if_fail (GECKO_IS_EMBED(embed), (char *)NULL);
+
+ browser = GET_BROWSER (embed);
+
+ if (browser->mWindow) {
+ NS_UTF16ToCString(browser->mWindow->mJSStatus,
+ NS_CSTRING_ENCODING_UTF8, tmpCString);
+ retval = g_strdup(tmpCString.get());
+ }
+
+ return retval;
+}
+
+char *
+gecko_embed_get_title (GeckoEmbed *embed)
+{
+ char *retval = nsnull;
+ GeckoBrowser *browser;
+ nsEmbedCString tmpCString;
+
+ g_return_val_if_fail (GECKO_IS_EMBED(embed), (char *)NULL);
+
+ browser = GET_BROWSER (embed);
+
+ if (browser->mWindow) {
+ NS_UTF16ToCString(browser->mWindow->mTitle,
+ NS_CSTRING_ENCODING_UTF8, tmpCString);
+ retval = g_strdup(tmpCString.get());
+ }
+
+ return retval;
+}
+
+char *
+gecko_embed_get_location (GeckoEmbed *embed)
+{
+ char *retval = nsnull;
+ GeckoBrowser *browser;
+
+ g_return_val_if_fail (GECKO_IS_EMBED(embed), (char *)NULL);
+
+ browser = GET_BROWSER (embed);
+
+ if (browser->mURI.Length()) {
+ retval = g_strdup(browser->mURI.get());
+ }
+
+ return retval;
+}
+
+void
+gecko_embed_reload (GeckoEmbed *embed,
+ gint32 flags)
+{
+ GeckoBrowser *browser;
+
+ g_return_if_fail (GECKO_IS_EMBED(embed));
+
+ browser = GET_BROWSER (embed);
+
+ PRUint32 reloadFlags = 0;
+
+ // map the external API to the internal web navigation API.
+ switch (flags) {
+ case GECKO_EMBED_FLAG_RELOADNORMAL:
+ reloadFlags = 0;
+ break;
+ case GECKO_EMBED_FLAG_RELOADBYPASSCACHE:
+ reloadFlags = nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE;
+ break;
+ case GECKO_EMBED_FLAG_RELOADBYPASSPROXY:
+ reloadFlags = nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
+ break;
+ case GECKO_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE:
+ reloadFlags = (nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY |
+ nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE);
+ break;
+ case GECKO_EMBED_FLAG_RELOADCHARSETCHANGE:
+ reloadFlags = nsIWebNavigation::LOAD_FLAGS_CHARSET_CHANGE;
+ break;
+ default:
+ reloadFlags = 0;
+ break;
+ }
+
+ browser->Reload(reloadFlags);
+}
+
+void
+gecko_embed_set_chrome_mask (GeckoEmbed *embed,
+ guint32 flags)
+{
+ GeckoBrowser *browser;
+
+ g_return_if_fail (GECKO_IS_EMBED(embed));
+
+ browser = GET_BROWSER (embed);
+
+ browser->SetChromeMask(flags);
+}
+
+guint32
+gecko_embed_get_chrome_mask (GeckoEmbed *embed)
+{
+ GeckoBrowser *browser;
+
+ g_return_val_if_fail (GECKO_IS_EMBED(embed), 0);
+
+ browser = GET_BROWSER (embed);
+
+ return browser->mChromeMask;
+}
+
+void
+gecko_embed_get_nsIWebBrowser (GeckoEmbed *embed,
+ nsIWebBrowser **retval)
+{
+ GeckoBrowser *browser;
+ *retval = nsnull;
+
+ g_return_if_fail (GECKO_IS_EMBED (embed));
+
+ browser = GET_BROWSER (embed);
+
+ if (browser->mWindow)
+ browser->mWindow->GetWebBrowser(retval);
+}
+
+GeckoBrowser *
+gecko_embed_get_GeckoBrowser (GeckoEmbed *embed)
+{
+ g_return_val_if_fail (GECKO_IS_EMBED (embed), nsnull);
+
+ return GET_BROWSER (embed);
+}
+
+static void
+gecko_embed_init (GeckoEmbed *embed)
+{
+ embed->priv = GECKO_EMBED_GET_PRIVATE (embed);
+
+ embed->priv->browser = new GeckoBrowser();
+ g_return_if_fail (embed->priv->browser);
+
+ gtk_widget_set_name (GTK_WIDGET (embed), "gecko_embed");
+
+ GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(embed), GTK_NO_WINDOW);
+}
+
+static void
+gecko_embed_class_init (GeckoEmbedClass *klass)
+{
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); // FIXME GObject
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+ parent_class = (GtkBinClass *) g_type_class_peek_parent (klass);
+
+ object_class->destroy = gecko_embed_destroy;
+
+ widget_class->realize = gecko_embed_realize;
+ widget_class->unrealize = gecko_embed_unrealize;
+ widget_class->size_allocate = gecko_embed_size_allocate;
+ widget_class->map = gecko_embed_map;
+ widget_class->unmap = gecko_embed_unmap;
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+ widget_class->get_accessible = gecko_embed_get_accessible;
+#endif
+
+ GType dom_param_types[1] = { GECKO_TYPE_DOM_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE };
+
+ gecko_embed_signals[DOM_KEY_DOWN] =
+ g_signal_newv ("dom-key-down",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_KEY_PRESS] =
+ g_signal_newv ("dom-key-press",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_KEY_UP] =
+ g_signal_newv ("dom-key-up",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_MOUSE_DOWN] =
+ g_signal_newv ("dom-mouse-down",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_MOUSE_UP] =
+ g_signal_newv ("dom-mouse-up",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_MOUSE_CLICK] =
+ g_signal_newv ("dom-mouse-click",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_MOUSE_DOUBLE_CLICK] =
+ g_signal_newv ("dom-mouse-dbl-click",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_MOUSE_OVER] =
+ g_signal_newv ("dom-mouse-over",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_MOUSE_OUT] =
+ g_signal_newv ("dom-mouse-out",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_MOUSE_OUT] =
+ g_signal_newv ("dom-focus-in",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_MOUSE_OUT] =
+ g_signal_newv ("dom-focus-out",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_MOUSE_OUT] =
+ g_signal_newv ("dom-activate",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[DOM_CONTEXT_MENU] =
+ g_signal_newv ("dom-context-menu",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ NULL,
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ G_N_ELEMENTS (dom_param_types),
+ dom_param_types);
+
+ gecko_embed_signals[OPEN_URI] =
+ g_signal_new ("open_uri",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, open_uri),
+ g_signal_accumulator_true_handled, NULL,
+ gecko_embed_marshal_BOOLEAN__STRING,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_STRING);
+
+ gecko_embed_signals[NET_START] =
+ g_signal_new ("net_start",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, net_start),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ gecko_embed_signals[NET_STOP] =
+ g_signal_new ("net_stop",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, net_stop),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ gecko_embed_signals[NET_STATE] =
+ g_signal_new ("net_state",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, net_state),
+ NULL, NULL,
+ gecko_embed_marshal_VOID__INT_UINT,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_INT,
+ G_TYPE_UINT);
+
+ gecko_embed_signals[NET_STATE_ALL] =
+ g_signal_new ("net_state_all",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, net_state_all),
+ NULL, NULL,
+ gecko_embed_marshal_VOID__STRING_INT_UINT,
+ G_TYPE_NONE,
+ 3,
+ G_TYPE_STRING,
+ G_TYPE_INT,
+ G_TYPE_UINT); // static scope? to avoid string copy? or G_TYPE_POINTER as 1st?
+
+ gecko_embed_signals[PROGRESS] =
+ g_signal_new ("progress",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, progress),
+ NULL, NULL,
+ gecko_embed_marshal_VOID__INT_INT,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_INT,
+ G_TYPE_INT);
+
+ gecko_embed_signals[PROGRESS_ALL] =
+ g_signal_new ("progress_all",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, progress_all),
+ NULL, NULL,
+ gecko_embed_marshal_VOID__STRING_INT_INT,
+ G_TYPE_NONE,
+ 3,
+ G_TYPE_STRING,
+ G_TYPE_INT,
+ G_TYPE_INT); // static scope?
+
+ gecko_embed_signals[SECURITY_CHANGE] =
+ g_signal_new ("security_change",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, security_change),
+ NULL, NULL,
+ gecko_embed_marshal_VOID__POINTER_UINT,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_POINTER,
+ G_TYPE_UINT);
+
+ gecko_embed_signals[STATUS_CHANGE] =
+ g_signal_new ("status_change",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, status_change),
+ NULL, NULL,
+ gecko_embed_marshal_VOID__POINTER_INT_POINTER,
+ G_TYPE_NONE,
+ 3,
+ G_TYPE_POINTER,
+ G_TYPE_INT,
+ G_TYPE_POINTER);
+
+ gecko_embed_signals[LINK_MESSAGE] =
+ g_signal_new ("link_message",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, link_message),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ gecko_embed_signals[JS_STATUS] =
+ g_signal_new ("js_status",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, js_status_message),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ gecko_embed_signals[LOCATION] =
+ g_signal_new ("location",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, location),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ gecko_embed_signals[TITLE] =
+ g_signal_new ("title",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, title),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ gecko_embed_signals[VISIBILITY] =
+ g_signal_new ("visibility",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, visibility),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_BOOLEAN);
+
+ gecko_embed_signals[DESTROY_BROWSER] =
+ g_signal_new ("destroy_browser",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, destroy_browser),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ gecko_embed_signals[SIZE_TO] =
+ g_signal_new ("size_to",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, size_to),
+ NULL, NULL,
+ gecko_embed_marshal_VOID__INT_INT,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_INT,
+ G_TYPE_INT);
+
+ gecko_embed_signals[NEW_WINDOW] =
+ g_signal_new ("new_window",
+ GECKO_TYPE_EMBED,
+ (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST),
+ G_STRUCT_OFFSET (GeckoEmbedClass, new_window),
+ NULL, NULL,
+ gecko_embed_marshal_VOID__OBJECT_UINT,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_OBJECT,
+ G_TYPE_UINT);
+
+ g_type_class_add_private (object_class, sizeof (GeckoEmbedPrivate));
+}
+
+GtkWidget *
+gecko_embed_new (void)
+{
+ return GTK_WIDGET (g_object_new (GECKO_TYPE_EMBED, NULL));
+}
diff --git a/embed/xulrunner/src/gecko-embed.h b/embed/xulrunner/src/gecko-embed.h
new file mode 100644
index 000000000..8aec90bc2
--- /dev/null
+++ b/embed/xulrunner/src/gecko-embed.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © Ramiro Estrugo
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * Ramiro Estrugo <ramiro@eazel.com>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef gecko_embed_h
+#define gecko_embed_h
+
+#include <stddef.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GECKO_TYPE_EMBED (gecko_embed_get_type())
+#define GECKO_EMBED(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GECKO_TYPE_EMBED, GeckoEmbed))
+#define GECKO_EMBED_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GECKO_TYPE_EMBED, GeckoEmbedClass))
+#define GECKO_IS_EMBED(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GECKO_TYPE_EMBED))
+#define GECKO_IS_EMBED_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GECKO_TYPE_EMBED))
+#define GECKO_EMBED_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GECKO_TYPE_EMBED, GeckoEmbedClass))
+
+typedef struct _GeckoEmbed GeckoEmbed;
+typedef struct _GeckoEmbedPrivate GeckoEmbedPrivate;
+typedef struct _GeckoEmbedClass GeckoEmbedClass;
+
+struct _GeckoEmbed
+{
+ GtkBin parent_instance;
+
+ /*< private >*/
+ GeckoEmbedPrivate *priv;
+};
+
+struct _GeckoEmbedClass
+{
+ GtkBinClass parent_class;
+
+ /* Signals */
+
+ /* Network */
+ gboolean (* open_uri) (GeckoEmbed *embed, const char *aURI);
+ void (* net_start) (GeckoEmbed *embed);
+ void (* net_stop) (GeckoEmbed *embed);
+ void (* net_state) (GeckoEmbed *embed, int state, guint status);
+ void (* net_state_all) (GeckoEmbed *embed, const char *aURI,
+ int state, guint status);
+ void (* progress) (GeckoEmbed *embed, int curprogress,
+ int maxprogress);
+ void (* progress_all) (GeckoEmbed *embed, const char *aURI,
+ int curprogress, int maxprogress);
+ void (* security_change) (GeckoEmbed *embed, gpointer request,
+ guint state);
+ void (* status_change) (GeckoEmbed *embed, gpointer request,
+ int status, gpointer message);
+
+ /* Document */
+ void (* link_message) (GeckoEmbed *embed);
+ void (* js_status_message) (GeckoEmbed *embed);
+ void (* location) (GeckoEmbed *embed);
+ void (* title) (GeckoEmbed *embed);
+ void (* visibility) (GeckoEmbed *embed, gboolean visibility);
+ void (* destroy_browser) (GeckoEmbed *embed);
+ void (* size_to) (GeckoEmbed *embed, int width, int height);
+
+
+ /* misc. */
+ void (* new_window) (GeckoEmbed *embed, GeckoEmbed **newEmbed,
+ guint chromemask);
+
+ /* reserved for future use */
+ void (* reserved_0) (void);
+ void (* reserved_1) (void);
+ void (* reserved_2) (void);
+ void (* reserved_3) (void);
+ void (* reserved_4) (void);
+ void (* reserved_5) (void);
+ void (* reserved_6) (void);
+ void (* reserved_7) (void);
+ void (* reserved_8) (void);
+ void (* reserved_9) (void);
+ void (* reserved_a) (void);
+ void (* reserved_b) (void);
+ void (* reserved_c) (void);
+ void (* reserved_d) (void);
+ void (* reserved_e) (void);
+ void (* reserved_f) (void);
+};
+
+GType gecko_embed_get_type (void);
+GtkWidget *gecko_embed_new (void);
+void gecko_embed_load_url (GeckoEmbed *embed,
+ const char *url);
+void gecko_embed_stop_load (GeckoEmbed *embed);
+gboolean gecko_embed_can_go_back (GeckoEmbed *embed);
+gboolean gecko_embed_can_go_forward (GeckoEmbed *embed);
+void gecko_embed_go_back (GeckoEmbed *embed);
+void gecko_embed_go_forward (GeckoEmbed *embed);
+void gecko_embed_render_data (GeckoEmbed *embed,
+ const char *data,
+ guint32 len,
+ const char *base_uri,
+ const char *mime_type);
+void gecko_embed_open_stream (GeckoEmbed *embed,
+ const char *base_uri,
+ const char *mime_type);
+void gecko_embed_append_data (GeckoEmbed *embed,
+ const char *data, guint32 len);
+void gecko_embed_close_stream (GeckoEmbed *embed);
+char *gecko_embed_get_link_message (GeckoEmbed *embed);
+char *gecko_embed_get_js_status (GeckoEmbed *embed);
+char *gecko_embed_get_title (GeckoEmbed *embed);
+char *gecko_embed_get_location (GeckoEmbed *embed);
+void gecko_embed_reload (GeckoEmbed *embed, gint32 flags);
+void gecko_embed_set_chrome_mask (GeckoEmbed *embed,
+ guint32 flags);
+guint32 gecko_embed_get_chrome_mask (GeckoEmbed *embed);
+
+G_END_DECLS
+
+#endif /* gecko_embed_h */
diff --git a/embed/xulrunner/src/gecko-init-internal.h b/embed/xulrunner/src/gecko-init-internal.h
new file mode 100644
index 000000000..551b4bd45
--- /dev/null
+++ b/embed/xulrunner/src/gecko-init-internal.h
@@ -0,0 +1,30 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Copyright © 2006 Xan Lopez <xan@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * $Id$
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __gecko_init_internal_h
+#define __gecko_init_internal_h
+
+#include <gtk/gtk.h>
+#include "nsIDirectoryService.h"
+
+extern gboolean gecko_init_with_params (const char *, const char*, const char*, nsIDirectoryServiceProvider*);
+
+#endif
diff --git a/embed/xulrunner/src/gecko-init-private.h b/embed/xulrunner/src/gecko-init-private.h
new file mode 100644
index 000000000..b4cc34bfb
--- /dev/null
+++ b/embed/xulrunner/src/gecko-init-private.h
@@ -0,0 +1,33 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Copyright © 2006 Xan Lopez <xan@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * $Id$
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __gecko_init_private_h
+#define __gecko_init_private_h
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void gecko_reparent_to_offscreen (GtkWidget*);
+
+G_END_DECLS
+
+#endif
diff --git a/embed/xulrunner/src/gecko-init.cpp b/embed/xulrunner/src/gecko-init.cpp
new file mode 100644
index 000000000..cbad02a67
--- /dev/null
+++ b/embed/xulrunner/src/gecko-init.cpp
@@ -0,0 +1,392 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include <config.h>
+
+#include <stdlib.h>
+
+#include "GeckoSingle.h"
+
+#include "nsIDocShell.h"
+#include "nsIWebProgress.h"
+#include "nsIWebBrowserStream.h"
+#include "nsIWidget.h"
+#include "nsIDirectoryService.h"
+#include "nsAppDirectoryServiceDefs.h"
+
+// for NS_APPSHELL_CID
+#include "nsWidgetsCID.h"
+
+// for do_GetInterface
+#include "nsIInterfaceRequestor.h"
+// for do_CreateInstance
+#include "nsIComponentManager.h"
+
+// for initializing our window watcher service
+#include "nsIWindowWatcher.h"
+
+#include "nsILocalFile.h"
+#include "nsXULAppAPI.h"
+
+// all of the crap that we need for event listeners
+// and when chrome windows finish loading
+#include "nsIDOMWindow.h"
+#include "nsPIDOMWindow.h"
+#include "nsIDOMWindowInternal.h"
+
+// For seting scrollbar visibilty
+#include <nsIDOMBarProp.h>
+
+// for the focus hacking we need to do
+#include "nsIFocusController.h"
+
+// app component registration
+#include "nsIGenericFactory.h"
+#include "nsIComponentRegistrar.h"
+
+// all of our local includes
+#include "gecko-init.h"
+#include "GeckoSingle.h"
+#include "EmbedWindow.h"
+#include "EmbedProgress.h"
+#include "EmbedContentListener.h"
+#include "EmbedEventListener.h"
+#include "EmbedWindowCreator.h"
+#include "GeckoPromptService.h"
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+#include "nsIAccessibilityService.h"
+#include "nsIAccessible.h"
+#include "nsIDOMDocument.h"
+#endif
+
+#include <nsServiceManagerUtils.h>
+#include "nsXPCOMGlue.h"
+
+#include "gecko-init.h"
+#include "gecko-init-private.h"
+#include "gecko-init-internal.h"
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(GeckoPromptService)
+
+static const nsModuleComponentInfo defaultAppComps[] = {
+ {
+ GECKO_PROMPT_SERVICE_CLASSNAME,
+ GECKO_PROMPT_SERVICE_CID,
+ "@mozilla.org/embedcomp/prompt-service;1",
+ GeckoPromptServiceConstructor
+ },
+#ifdef HAVE_NSINONBLOCKINGALERTSERVICE_H
+ {
+ GECKO_PROMPT_SERVICE_CLASSNAME,
+ GECKO_PROMPT_SERVICE_CID,
+ "@mozilla.org/embedcomp/nbalert-service;1",
+ GeckoPromptServiceConstructor
+ },
+#endif /* HAVE_NSINONBLOCKINGALERTSERVICE_H */
+};
+
+GtkWidget *sOffscreenWindow = 0;
+GtkWidget *sOffscreenFixed = 0;
+const nsModuleComponentInfo *sAppComps = defaultAppComps;
+int sNumAppComps = sizeof (defaultAppComps) / sizeof (nsModuleComponentInfo);
+nsILocalFile *sProfileDir = nsnull;
+nsISupports *sProfileLock = nsnull;
+nsIDirectoryServiceProvider* sAppFileLocProvider;
+
+class GTKEmbedDirectoryProvider : public nsIDirectoryServiceProvider2
+{
+ public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
+};
+
+static const GTKEmbedDirectoryProvider kDirectoryProvider;
+
+NS_IMPL_QUERY_INTERFACE2(GTKEmbedDirectoryProvider,
+ nsIDirectoryServiceProvider,
+ nsIDirectoryServiceProvider2)
+
+NS_IMETHODIMP_(nsrefcnt)
+GTKEmbedDirectoryProvider::AddRef()
+{
+ return 2;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+GTKEmbedDirectoryProvider::Release()
+{
+ return 1;
+}
+
+NS_IMETHODIMP
+GTKEmbedDirectoryProvider::GetFile(const char *aKey, PRBool *aPersist,
+ nsIFile* *aResult)
+{
+ if (sAppFileLocProvider) {
+ nsresult rv = sAppFileLocProvider->GetFile(aKey, aPersist,
+ aResult);
+ if (NS_SUCCEEDED(rv))
+ return rv;
+ }
+
+ if (sProfileDir && !strcmp(aKey, NS_APP_USER_PROFILE_50_DIR)) {
+ *aPersist = PR_TRUE;
+ return sProfileDir->Clone(aResult);
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+GTKEmbedDirectoryProvider::GetFiles(const char *aKey,
+ nsISimpleEnumerator* *aResult)
+{
+ nsCOMPtr<nsIDirectoryServiceProvider2>
+ dp2(do_QueryInterface(sAppFileLocProvider));
+
+ if (!dp2)
+ return NS_ERROR_FAILURE;
+
+ return dp2->GetFiles(aKey, aResult);
+}
+
+/* static */
+nsresult
+RegisterAppComponents(void)
+{
+ nsCOMPtr<nsIComponentRegistrar> cr;
+ nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(cr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIComponentManager> cm;
+ rv = NS_GetComponentManager (getter_AddRefs (cm));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ for (int i = 0; i < sNumAppComps; ++i) {
+ nsCOMPtr<nsIGenericFactory> componentFactory;
+ rv = NS_NewGenericFactory(getter_AddRefs(componentFactory),
+ &(sAppComps[i]));
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Unable to create factory for component");
+ continue; // don't abort registering other components
+ }
+
+ rv = cr->RegisterFactory(sAppComps[i].mCID, sAppComps[i].mDescription,
+ sAppComps[i].mContractID, componentFactory);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to register factory for component");
+
+ // Call the registration hook of the component, if any
+ if (sAppComps[i].mRegisterSelfProc) {
+ rv = sAppComps[i].mRegisterSelfProc(cm, nsnull, nsnull, nsnull,
+ &(sAppComps[i]));
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to self-register component");
+ }
+ }
+
+ return rv;
+}
+
+/* static */
+nsresult
+StartupProfile (const char* aProfileDir, const char* aProfileName)
+{
+ /* Running without profile */
+ if (!aProfileDir || !aProfileName)
+ return NS_OK;
+
+ if (sProfileDir && GeckoSingle::sWidgetCount != 0) {
+ NS_ERROR("Cannot change profile directory during run!");
+ return NS_ERROR_ALREADY_INITIALIZED;
+ }
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> profileDir;
+ rv = NS_NewNativeLocalFile (nsDependentCString (aProfileDir), PR_TRUE,
+ &sProfileDir);
+ if (NS_FAILED (rv))
+ return rv;
+
+ if (aProfileName) {
+ rv = sProfileDir->AppendNative (nsDependentCString (aProfileName));
+ if (NS_FAILED (rv))
+ return rv; // FIXMEchpe release sProfileDir
+ }
+
+ rv = XRE_LockProfileDirectory (sProfileDir, &sProfileLock);
+ if (NS_FAILED (rv))
+ return rv; // FIXMEchpe release sProfileDir
+
+ if (GeckoSingle::sWidgetCount)
+ XRE_NotifyProfile();
+
+ return NS_OK;
+}
+
+gboolean
+gecko_init ()
+{
+ return gecko_init_with_params (nsnull, nsnull, nsnull, nsnull);
+}
+
+gboolean
+gecko_init_with_profile (const char *aGREPath,
+ const char* aProfileDir,
+ const char* aProfileName)
+{
+ return gecko_init_with_params (aGREPath, aProfileDir, aProfileName, nsnull);
+}
+
+gboolean
+gecko_init_with_params (const char *aGREPath,
+ const char* aProfileDir,
+ const char* aProfileName,
+ nsIDirectoryServiceProvider* aAppFileLocProvider)
+{
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> binDir;
+
+#if 0 //def XPCOM_GLUE
+ const char* xpcomLocation = GRE_GetXPCOMPath();
+
+ // Startup the XPCOM Glue that links us up with XPCOM.
+ nsresult rv = XPCOMGlueStartup(xpcomLocation);
+ if (NS_FAILED(rv)) return;
+#endif
+
+ NS_IF_ADDREF (sAppFileLocProvider = aAppFileLocProvider);
+
+ /* FIrst try to lock the profile */
+ rv = StartupProfile (aProfileDir, aProfileName);
+ if (NS_FAILED (rv))
+ return FALSE;
+
+ const char* aCompPath = g_getenv("GECKO_HOME");
+
+ if (aCompPath) {
+ rv = NS_NewNativeLocalFile(nsEmbedCString(aCompPath), PR_TRUE, getter_AddRefs(binDir));
+ NS_ENSURE_SUCCESS(rv,false);
+ }
+
+ if (!aGREPath)
+ aGREPath = getenv("MOZILLA_FIVE_HOME");
+
+ if (!aGREPath)
+ return FALSE;
+
+ nsCOMPtr<nsILocalFile> greDir;
+ rv = NS_NewNativeLocalFile (nsDependentCString (aGREPath), PR_TRUE,
+ getter_AddRefs (greDir));
+ if (NS_FAILED(rv))
+ return FALSE;
+
+ rv = XRE_InitEmbedding(greDir, binDir,
+ const_cast<GTKEmbedDirectoryProvider*> (&kDirectoryProvider),
+ nsnull, nsnull);
+ if (NS_FAILED (rv))
+ return FALSE;
+
+ if (sProfileDir)
+ XRE_NotifyProfile();
+
+ rv = RegisterAppComponents();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Warning: Failed to register app components.\n");
+
+ // create our local object
+ EmbedWindowCreator *creator = new EmbedWindowCreator();
+ nsCOMPtr<nsIWindowCreator> windowCreator =
+ static_cast<nsIWindowCreator *>(creator);
+
+ // Attach it via the watcher service
+ nsCOMPtr<nsIWindowWatcher> watcher (do_GetService(NS_WINDOWWATCHER_CONTRACTID));
+ if (watcher)
+ watcher->SetWindowCreator(windowCreator);
+
+ return true;
+}
+
+/* static */
+void
+EnsureOffscreenWindow(void)
+{
+ if (sOffscreenWindow)
+ return;
+
+ sOffscreenWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_realize (sOffscreenWindow);
+ sOffscreenFixed = gtk_fixed_new();
+ gtk_container_add (GTK_CONTAINER (sOffscreenWindow), sOffscreenFixed);
+ gtk_widget_realize (sOffscreenFixed);
+}
+
+/* static */
+void
+gecko_reparent_to_offscreen(GtkWidget *aWidget)
+{
+ EnsureOffscreenWindow();
+
+ gtk_widget_reparent(aWidget, sOffscreenFixed);
+}
+
+/* static */
+void
+DestroyOffscreenWindow(void)
+{
+ if (!sOffscreenWindow)
+ return;
+ gtk_widget_destroy(sOffscreenWindow);
+ sOffscreenWindow = nsnull;
+ sOffscreenFixed = nsnull;
+}
+
+void
+gecko_shutdown()
+{
+ // destroy the offscreen window
+ DestroyOffscreenWindow();
+
+ NS_IF_RELEASE (sProfileDir);
+
+ // shut down XPCOM/Embedding
+ XRE_TermEmbedding();
+
+ // we no longer need a reference to the DirectoryServiceProvider
+ NS_IF_RELEASE (sAppFileLocProvider);
+
+ /* FIXMchpe before or after TermEmbedding?? */
+ NS_IF_RELEASE (sProfileLock);
+}
diff --git a/embed/xulrunner/src/gecko-init.h b/embed/xulrunner/src/gecko-init.h
new file mode 100644
index 000000000..ee66f0ea4
--- /dev/null
+++ b/embed/xulrunner/src/gecko-init.h
@@ -0,0 +1,35 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Copyright © 2006 Xan Lopez <xan@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * $Id$
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __gecko_init_h
+#define __gecko_init_h
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+gboolean gecko_init ();
+gboolean gecko_init_with_profile (const char *, const char*, const char*);
+void gecko_shutdown ();
+
+G_END_DECLS
+
+#endif
diff --git a/embed/xulrunner/tests/Makefile.am b/embed/xulrunner/tests/Makefile.am
new file mode 100644
index 000000000..22a2cf93a
--- /dev/null
+++ b/embed/xulrunner/tests/Makefile.am
@@ -0,0 +1,35 @@
+required = \
+ xpcom \
+ string \
+ dom
+
+bin_PROGRAMS = testgeckoembed
+
+testgeckoembed_SOURCES = \
+ testgeckoembed.cpp
+
+testgeckoembed_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/embed/gecko/src \
+ -I$(top_builddir)/embed/gecko/src \
+ $(addprefix -I$(GECKO_INCLUDE_ROOT)/,$(required)) \
+ -I$(GECKO_INCLUDE_ROOT) \
+ -DGECKO_HOME=\"$(GECKO_HOME)\" \
+ $(AM_CPPFLAGS)
+
+testgeckoembed_CXXFLAGS = \
+ $(GGE_DEPENDENCY_CFLAGS) \
+ $(GECKO_CFLAGS) \
+ $(AM_CXXFLAGS)
+
+testgeckoembed_LDADD = \
+ $(top_builddir)/embed/gecko/src/libgnomegeckoembed-0.0.la \
+ $(GGE_DEPENDENCY_LIBS) \
+ $(GECKO_LIBS) \
+ $(GECKO_EXTRA_LIBS) \
+ $(GECKO_GLUE_LIBS) \
+ -lxpcomglue
+
+testgeckoembed_LDFLAGS = \
+ -R$(GECKO_HOME)
+# `$(MOZILLA_CONFIG) --libs $(required)`
diff --git a/embed/xulrunner/tests/TestGtkEmbedNotebook.cpp b/embed/xulrunner/tests/TestGtkEmbedNotebook.cpp
new file mode 100644
index 000000000..1891ca06b
--- /dev/null
+++ b/embed/xulrunner/tests/TestGtkEmbedNotebook.cpp
@@ -0,0 +1,49 @@
+#include <gtk/gtk.h>
+#include <gtkmozembed.h>
+int main(int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *label;
+ GtkWidget *mozembed;
+ GtkWidget *container;
+ char *url;
+
+ gtk_init(&argc, &argv);
+
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ container = gtk_notebook_new();
+ mozembed = gtk_moz_embed_new();
+ label = gtk_label_new("Can you see this message?\n"
+ "Once you switch to mozembed page "
+ "you never see this message.");
+
+ gtk_signal_connect(GTK_OBJECT(mozembed), "destroy",
+ GTK_SIGNAL_FUNC(gtk_main_quit),
+NULL);
+
+ gtk_container_add(GTK_CONTAINER(window), container);
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(container),
+ label,
+ gtk_label_new("gtk label"));
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(container),
+ mozembed,
+ gtk_label_new("mozembed"));
+
+
+
+
+ gtk_widget_set_usize(window, 400, 300);
+ gtk_widget_show(mozembed);
+ gtk_widget_show(label);
+ gtk_widget_show_all(window);
+
+ url = (argc > 1) ? argv[1] : (char *)"localhost";
+ gtk_moz_embed_load_url(GTK_MOZ_EMBED(mozembed), url);
+
+ gtk_main();
+
+ return 0;
+}
diff --git a/embed/xulrunner/tests/testgeckoembed.cpp b/embed/xulrunner/tests/testgeckoembed.cpp
new file mode 100644
index 000000000..1b9a888b6
--- /dev/null
+++ b/embed/xulrunner/tests/testgeckoembed.cpp
@@ -0,0 +1,1145 @@
+/*
+ * Copyright © Christopher Blizzard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include <config.h>
+
+#include "gecko-init.h"
+#include "gecko-embed.h"
+#include "gecko-embed-single.h"
+#include "gecko-dom-event.h"
+#include "gecko-dom-event-internal.h"
+#include "gecko-embed-types.h"
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+// mozilla specific headers
+#include "nsIDOMKeyEvent.h"
+#include "nsIDOMMouseEvent.h"
+#include "nsIDOMUIEvent.h"
+
+#include <nsStringAPI.h>
+#include <nsCOMPtr.h>
+
+#define XPCOM_GLUE
+#include <nsXPCOMGlue.h>
+
+typedef struct _TestGeckoBrowser {
+ GtkWidget *topLevelWindow;
+ GtkWidget *topLevelVBox;
+ GtkWidget *menuBar;
+ GtkWidget *fileMenuItem;
+ GtkWidget *fileMenu;
+ GtkWidget *fileOpenNewBrowser;
+ GtkWidget *fileStream;
+ GtkWidget *fileClose;
+ GtkWidget *fileQuit;
+ GtkWidget *toolbarHBox;
+ GtkWidget *toolbar;
+ GtkWidget *backButton;
+ GtkWidget *stopButton;
+ GtkWidget *forwardButton;
+ GtkWidget *reloadButton;
+ GtkWidget *urlEntry;
+ GtkWidget *mozEmbed;
+ GtkWidget *progressAreaHBox;
+ GtkWidget *progressBar;
+ GtkWidget *statusAlign;
+ GtkWidget *statusBar;
+ const char *statusMessage;
+ int loadPercent;
+ int bytesLoaded;
+ int maxBytesLoaded;
+ char *tempMessage;
+ gboolean menuBarOn;
+ gboolean toolBarOn;
+ gboolean locationBarOn;
+ gboolean statusBarOn;
+
+} TestGeckoBrowser;
+
+// the list of browser windows currently open
+GList *browser_list = g_list_alloc();
+
+static TestGeckoBrowser *new_gecko_browser (guint32 chromeMask);
+static void set_browser_visibility (TestGeckoBrowser *browser,
+ gboolean visibility);
+
+static int num_browsers = 0;
+
+// callbacks from the UI
+static void back_clicked_cb (GtkButton *button,
+ TestGeckoBrowser *browser);
+static void stop_clicked_cb (GtkButton *button,
+ TestGeckoBrowser *browser);
+static void forward_clicked_cb (GtkButton *button,
+ TestGeckoBrowser *browser);
+static void reload_clicked_cb (GtkButton *button,
+ TestGeckoBrowser *browser);
+static void url_activate_cb (GtkEditable *widget,
+ TestGeckoBrowser *browser);
+static void menu_open_new_cb (GtkMenuItem *menuitem,
+ TestGeckoBrowser *browser);
+static void menu_stream_cb (GtkMenuItem *menuitem,
+ TestGeckoBrowser *browser);
+static void menu_close_cb (GtkMenuItem *menuitem,
+ TestGeckoBrowser *browser);
+static void menu_quit_cb (GtkMenuItem *menuitem,
+ TestGeckoBrowser *browser);
+static gboolean delete_cb (GtkWidget *widget, GdkEventAny *event,
+ TestGeckoBrowser *browser);
+static void destroy_cb (GtkWidget *widget,
+ TestGeckoBrowser *browser);
+
+// callbacks from the widget
+static void location_changed_cb (GeckoEmbed *embed, TestGeckoBrowser *browser);
+static void title_changed_cb (GeckoEmbed *embed, TestGeckoBrowser *browser);
+static void load_started_cb (GeckoEmbed *embed, TestGeckoBrowser *browser);
+static void load_finished_cb (GeckoEmbed *embed, TestGeckoBrowser *browser);
+static void net_state_change_cb (GeckoEmbed *embed, gint flags,
+ guint status, TestGeckoBrowser *browser);
+static void net_state_change_all_cb (GeckoEmbed *embed, const char *uri,
+ gint flags, guint status,
+ TestGeckoBrowser *browser);
+static void progress_change_cb (GeckoEmbed *embed, gint cur, gint max,
+ TestGeckoBrowser *browser);
+static void progress_change_all_cb (GeckoEmbed *embed, const char *uri,
+ gint cur, gint max,
+ TestGeckoBrowser *browser);
+static void link_message_cb (GeckoEmbed *embed, TestGeckoBrowser *browser);
+static void js_status_cb (GeckoEmbed *embed, TestGeckoBrowser *browser);
+static void new_window_cb (GeckoEmbed *embed,
+ GeckoEmbed **retval, guint chromemask,
+ TestGeckoBrowser *browser);
+static void visibility_cb (GeckoEmbed *embed,
+ gboolean visibility,
+ TestGeckoBrowser *browser);
+static void destroy_brsr_cb (GeckoEmbed *embed, TestGeckoBrowser *browser);
+static gint open_uri_cb (GeckoEmbed *embed, const char *uri,
+ TestGeckoBrowser *browser);
+static void size_to_cb (GeckoEmbed *embed, gint width,
+ gint height, TestGeckoBrowser *browser);
+static gboolean dom_key_down_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_key_press_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_key_up_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_mouse_down_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_mouse_up_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_mouse_click_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_mouse_dbl_click_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_mouse_over_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_mouse_out_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_activate_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_focus_in_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_focus_out_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+static gboolean dom_context_menu_cb (GeckoEmbed *, GeckoDOMEvent *event,
+ TestGeckoBrowser *browser);
+
+// callbacks from the singleton object
+static void new_window_orphan_cb (GeckoEmbedSingle *embed,
+ GeckoEmbed **retval, guint chromemask,
+ gpointer data);
+
+// some utility functions
+static void update_status_bar_text (TestGeckoBrowser *browser);
+static void update_temp_message (TestGeckoBrowser *browser,
+ const char *message);
+static void update_nav_buttons (TestGeckoBrowser *browser);
+
+int
+main(int argc, char **argv)
+{
+ //g_setenv ("MOZILLA_FIVE_HOME", GECKO_HOME, FALSE);
+
+ gtk_init(&argc, &argv);
+
+ static const GREVersionRange greVersion = {
+ "1.9a", PR_TRUE,
+ "2", PR_TRUE
+ };
+
+ char xpcomPath[PATH_MAX];
+
+ nsresult rv = GRE_GetGREPathWithProperties(&greVersion, 1, nsnull, 0,
+ xpcomPath, sizeof(xpcomPath));
+ if (NS_FAILED(rv)) {
+ fprintf(stderr, "Couldn't find a compatible GRE.\n");
+ return 1;
+ }
+
+ rv = XPCOMGlueStartup(xpcomPath);
+ if (NS_FAILED(rv)) {
+ fprintf(stderr, "Couldn't start XPCOM.");
+ return 1;
+ }
+
+ char *lastSlash = strrchr(xpcomPath, '/');
+ if (lastSlash)
+ *lastSlash = '\0';
+
+
+ char *home_path;
+ char *full_path;
+ home_path = getenv("HOME");
+ if (!home_path) {
+ fprintf(stderr, "Failed to get HOME\n");
+ exit(1);
+ }
+
+
+ full_path = g_strdup_printf("%s/%s", home_path, ".TestGtkEmbed");
+
+ if (!gecko_init_with_profile (xpcomPath, full_path, "TestGtkEmbed")) {
+ fprintf(stderr, "Failed gecko_init_with_profile\n");
+ exit(1);
+ }
+
+ // get the singleton object and hook up to its new window callback
+ // so we can create orphaned windows.
+
+ GeckoEmbedSingle *single;
+
+ single = gecko_embed_single_get();
+ if (!single) {
+ fprintf(stderr, "Failed to get singleton embed object!\n");
+ exit(1);
+ }
+
+ g_signal_connect (single, "new-window-orphan",
+ G_CALLBACK (new_window_orphan_cb), NULL);
+
+
+ TestGeckoBrowser *browser = new_gecko_browser(GECKO_EMBED_FLAG_DEFAULTCHROME);
+
+ // set our minimum size
+ gtk_widget_set_usize(browser->mozEmbed, 400, 400);
+
+ set_browser_visibility(browser, TRUE);
+
+ if (argc > 1)
+ gecko_embed_load_url(GECKO_EMBED(browser->mozEmbed), argv[1]);
+
+ gtk_main();
+
+ gecko_shutdown ();
+}
+
+static TestGeckoBrowser *
+new_gecko_browser(guint32 chromeMask)
+{
+ guint32 actualChromeMask = chromeMask;
+ TestGeckoBrowser *browser = 0;
+
+ num_browsers++;
+
+ browser = g_new0(TestGeckoBrowser, 1);
+
+ browser_list = g_list_prepend(browser_list, browser);
+
+ browser->menuBarOn = FALSE;
+ browser->toolBarOn = FALSE;
+ browser->locationBarOn = FALSE;
+ browser->statusBarOn = FALSE;
+
+ g_print("new_gecko_browser\n");
+
+// if (chromeMask == GECKO_EMBED_FLAG_DEFAULTCHROME)
+// actualChromeMask = GECKO_EMBED_FLAG_ALLCHROME;
+
+ /* FIXMEchpe find out WHY the chrome masks we get from gecko as so weird */
+ actualChromeMask = 0xffffffff;
+
+ if (actualChromeMask & GECKO_EMBED_FLAG_MENUBARON)
+ {
+ browser->menuBarOn = TRUE;
+ g_print("\tmenu bar\n");
+ }
+ if (actualChromeMask & GECKO_EMBED_FLAG_TOOLBARON)
+ {
+ browser->toolBarOn = TRUE;
+ g_print("\ttool bar\n");
+ }
+ if (actualChromeMask & GECKO_EMBED_FLAG_LOCATIONBARON)
+ {
+ browser->locationBarOn = TRUE;
+ g_print("\tlocation bar\n");
+ }
+ if (actualChromeMask & GECKO_EMBED_FLAG_STATUSBARON)
+ {
+ browser->statusBarOn = TRUE;
+ g_print("\tstatus bar\n");
+ }
+
+ // create our new toplevel window
+ browser->topLevelWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ // new vbox
+ browser->topLevelVBox = gtk_vbox_new(FALSE, 0);
+ // add it to the toplevel window
+ gtk_container_add(GTK_CONTAINER(browser->topLevelWindow),
+ browser->topLevelVBox);
+ // create our menu bar
+ browser->menuBar = gtk_menu_bar_new();
+ // create the file menu
+ browser->fileMenuItem = gtk_menu_item_new_with_label("File");
+ browser->fileMenu = gtk_menu_new();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM(browser->fileMenuItem),
+ browser->fileMenu);
+
+ browser->fileOpenNewBrowser =
+ gtk_menu_item_new_with_label("Open New Browser");
+ gtk_menu_append(GTK_MENU(browser->fileMenu),
+ browser->fileOpenNewBrowser);
+
+ browser->fileStream =
+ gtk_menu_item_new_with_label("Test Stream");
+ gtk_menu_append(GTK_MENU(browser->fileMenu),
+ browser->fileStream);
+
+ browser->fileClose =
+ gtk_menu_item_new_with_label("Close");
+ gtk_menu_append(GTK_MENU(browser->fileMenu),
+ browser->fileClose);
+
+ browser->fileQuit =
+ gtk_menu_item_new_with_label("Quit");
+ gtk_menu_append(GTK_MENU(browser->fileMenu),
+ browser->fileQuit);
+
+ // append it
+ gtk_menu_bar_append(GTK_MENU_BAR(browser->menuBar), browser->fileMenuItem);
+
+ // add it to the vbox
+ gtk_box_pack_start(GTK_BOX(browser->topLevelVBox),
+ browser->menuBar,
+ FALSE, // expand
+ FALSE, // fill
+ 0); // padding
+ // create the hbox that will contain the toolbar and the url text entry bar
+ browser->toolbarHBox = gtk_hbox_new(FALSE, 0);
+ // add that hbox to the vbox
+ gtk_box_pack_start(GTK_BOX(browser->topLevelVBox),
+ browser->toolbarHBox,
+ FALSE, // expand
+ FALSE, // fill
+ 0); // padding
+ // new horiz toolbar with buttons + icons
+ browser->toolbar = gtk_toolbar_new();
+ gtk_toolbar_set_orientation(GTK_TOOLBAR(browser->toolbar),
+ GTK_ORIENTATION_HORIZONTAL);
+ gtk_toolbar_set_style(GTK_TOOLBAR(browser->toolbar),
+ GTK_TOOLBAR_BOTH);
+
+ // add it to the hbox
+ gtk_box_pack_start(GTK_BOX(browser->toolbarHBox), browser->toolbar,
+ FALSE, // expand
+ FALSE, // fill
+ 0); // padding
+ // new back button
+ browser->backButton =
+ gtk_toolbar_append_item(GTK_TOOLBAR(browser->toolbar),
+ "Back",
+ "Go Back",
+ "Go Back",
+ 0, // XXX replace with icon
+ GTK_SIGNAL_FUNC(back_clicked_cb),
+ browser);
+ // new stop button
+ browser->stopButton =
+ gtk_toolbar_append_item(GTK_TOOLBAR(browser->toolbar),
+ "Stop",
+ "Stop",
+ "Stop",
+ 0, // XXX replace with icon
+ GTK_SIGNAL_FUNC(stop_clicked_cb),
+ browser);
+ // new forward button
+ browser->forwardButton =
+ gtk_toolbar_append_item(GTK_TOOLBAR(browser->toolbar),
+ "Forward",
+ "Forward",
+ "Forward",
+ 0, // XXX replace with icon
+ GTK_SIGNAL_FUNC(forward_clicked_cb),
+ browser);
+ // new reload button
+ browser->reloadButton =
+ gtk_toolbar_append_item(GTK_TOOLBAR(browser->toolbar),
+ "Reload",
+ "Reload",
+ "Reload",
+ 0, // XXX replace with icon
+ GTK_SIGNAL_FUNC(reload_clicked_cb),
+ browser);
+ // create the url text entry
+ browser->urlEntry = gtk_entry_new();
+ // add it to the hbox
+ gtk_box_pack_start(GTK_BOX(browser->toolbarHBox), browser->urlEntry,
+ TRUE, // expand
+ TRUE, // fill
+ 0); // padding
+ // create our new gtk moz embed widget
+ browser->mozEmbed = gecko_embed_new();
+ // add it to the toplevel vbox
+ gtk_box_pack_start(GTK_BOX(browser->topLevelVBox), browser->mozEmbed,
+ TRUE, // expand
+ TRUE, // fill
+ 0); // padding
+ // create the new hbox for the progress area
+ browser->progressAreaHBox = gtk_hbox_new(FALSE, 0);
+ // add it to the vbox
+ gtk_box_pack_start(GTK_BOX(browser->topLevelVBox), browser->progressAreaHBox,
+ FALSE, // expand
+ FALSE, // fill
+ 0); // padding
+ // create our new progress bar
+ browser->progressBar = gtk_progress_bar_new();
+ // add it to the hbox
+ gtk_box_pack_start(GTK_BOX(browser->progressAreaHBox), browser->progressBar,
+ FALSE, // expand
+ FALSE, // fill
+ 0); // padding
+
+ // create our status area and the alignment object that will keep it
+ // from expanding
+ browser->statusAlign = gtk_alignment_new(0, 0, 1, 1);
+ gtk_widget_set_usize(browser->statusAlign, 1, -1);
+ // create the status bar
+ browser->statusBar = gtk_statusbar_new();
+ gtk_container_add(GTK_CONTAINER(browser->statusAlign), browser->statusBar);
+ // add it to the hbox
+ gtk_box_pack_start(GTK_BOX(browser->progressAreaHBox), browser->statusAlign,
+ TRUE, // expand
+ TRUE, // fill
+ 0); // padding
+ // by default none of the buttons are marked as sensitive.
+ gtk_widget_set_sensitive(browser->backButton, FALSE);
+ gtk_widget_set_sensitive(browser->stopButton, FALSE);
+ gtk_widget_set_sensitive(browser->forwardButton, FALSE);
+ gtk_widget_set_sensitive(browser->reloadButton, FALSE);
+
+ // catch the destruction of the toplevel window
+ gtk_signal_connect(GTK_OBJECT(browser->topLevelWindow), "delete_event",
+ GTK_SIGNAL_FUNC(delete_cb), browser);
+
+ // hook up the activate signal to the right callback
+ gtk_signal_connect(GTK_OBJECT(browser->urlEntry), "activate",
+ GTK_SIGNAL_FUNC(url_activate_cb), browser);
+
+ // hook up to the open new browser activation
+ gtk_signal_connect(GTK_OBJECT(browser->fileOpenNewBrowser), "activate",
+ GTK_SIGNAL_FUNC(menu_open_new_cb), browser);
+ // hook up to the stream test
+ gtk_signal_connect(GTK_OBJECT(browser->fileStream), "activate",
+ GTK_SIGNAL_FUNC(menu_stream_cb), browser);
+ // close this window
+ gtk_signal_connect(GTK_OBJECT(browser->fileClose), "activate",
+ GTK_SIGNAL_FUNC(menu_close_cb), browser);
+ // quit the application
+ gtk_signal_connect(GTK_OBJECT(browser->fileQuit), "activate",
+ GTK_SIGNAL_FUNC(menu_quit_cb), browser);
+
+ // hook up the location change to update the urlEntry
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "location",
+ GTK_SIGNAL_FUNC(location_changed_cb), browser);
+ // hook up the title change to update the window title
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "title",
+ GTK_SIGNAL_FUNC(title_changed_cb), browser);
+ // hook up the start and stop signals
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "net_start",
+ GTK_SIGNAL_FUNC(load_started_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "net_stop",
+ GTK_SIGNAL_FUNC(load_finished_cb), browser);
+ // hook up to the change in network status
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "net_state",
+ GTK_SIGNAL_FUNC(net_state_change_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "net_state_all",
+ GTK_SIGNAL_FUNC(net_state_change_all_cb), browser);
+ // hookup to changes in progress
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "progress",
+ GTK_SIGNAL_FUNC(progress_change_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "progress_all",
+ GTK_SIGNAL_FUNC(progress_change_all_cb), browser);
+ // hookup to changes in over-link message
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "link_message",
+ GTK_SIGNAL_FUNC(link_message_cb), browser);
+ // hookup to changes in js status message
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "js_status",
+ GTK_SIGNAL_FUNC(js_status_cb), browser);
+ // hookup to see whenever a new window is requested
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "new_window",
+ GTK_SIGNAL_FUNC(new_window_cb), browser);
+ // hookup to any requested visibility changes
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "visibility",
+ GTK_SIGNAL_FUNC(visibility_cb), browser);
+ // hookup to the signal that says that the browser requested to be
+ // destroyed
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "destroy_browser",
+ GTK_SIGNAL_FUNC(destroy_brsr_cb), browser);
+ // hookup to the signal that is called when someone clicks on a link
+ // to load a new uri
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "open_uri",
+ GTK_SIGNAL_FUNC(open_uri_cb), browser);
+ // this signal is emitted when there's a request to change the
+ // containing browser window to a certain height, like with width
+ // and height args for a window.open in javascript
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "size_to",
+ GTK_SIGNAL_FUNC(size_to_cb), browser);
+ // key event signals
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_key_down",
+ GTK_SIGNAL_FUNC(dom_key_down_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_key_press",
+ GTK_SIGNAL_FUNC(dom_key_press_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_key_up",
+ GTK_SIGNAL_FUNC(dom_key_up_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_down",
+ GTK_SIGNAL_FUNC(dom_mouse_down_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_up",
+ GTK_SIGNAL_FUNC(dom_mouse_up_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_click",
+ GTK_SIGNAL_FUNC(dom_mouse_click_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_dbl_click",
+ GTK_SIGNAL_FUNC(dom_mouse_dbl_click_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_over",
+ GTK_SIGNAL_FUNC(dom_mouse_over_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_out",
+ GTK_SIGNAL_FUNC(dom_mouse_out_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_activate",
+ GTK_SIGNAL_FUNC(dom_activate_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_focus_in",
+ GTK_SIGNAL_FUNC(dom_focus_in_cb), browser);
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_focus_out",
+ GTK_SIGNAL_FUNC(dom_focus_out_cb), browser);
+ g_signal_connect(browser->mozEmbed, "dom-context-menu",
+ GTK_SIGNAL_FUNC(dom_context_menu_cb), browser);
+ // hookup to when the window is destroyed
+ gtk_signal_connect(GTK_OBJECT(browser->mozEmbed), "destroy",
+ GTK_SIGNAL_FUNC(destroy_cb), browser);
+
+ // set the chrome type so it's stored in the object
+ gecko_embed_set_chrome_mask(GECKO_EMBED(browser->mozEmbed),
+ actualChromeMask);
+
+ gtk_widget_show_all (browser->topLevelVBox);
+
+ return browser;
+}
+
+void
+set_browser_visibility (TestGeckoBrowser *browser, gboolean visibility)
+{
+ if (!visibility)
+ {
+ gtk_widget_hide(browser->topLevelWindow);
+ return;
+ }
+
+ if (browser->menuBarOn)
+ gtk_widget_show_all(browser->menuBar);
+ else
+ gtk_widget_hide_all(browser->menuBar);
+
+ // since they are on the same line here...
+ if (browser->toolBarOn || browser->locationBarOn)
+ gtk_widget_show_all(browser->toolbarHBox);
+ else
+ gtk_widget_hide_all(browser->toolbarHBox);
+
+ if (browser->statusBarOn)
+ gtk_widget_show_all(browser->progressAreaHBox);
+ else
+ gtk_widget_hide_all(browser->progressAreaHBox);
+
+ gtk_widget_show(browser->mozEmbed);
+ gtk_widget_show(browser->topLevelVBox);
+ gtk_widget_show(browser->topLevelWindow);
+}
+
+void
+back_clicked_cb (GtkButton *button, TestGeckoBrowser *browser)
+{
+ gecko_embed_go_back(GECKO_EMBED(browser->mozEmbed));
+}
+
+void
+stop_clicked_cb (GtkButton *button, TestGeckoBrowser *browser)
+{
+ g_print("stop_clicked_cb\n");
+ gecko_embed_stop_load(GECKO_EMBED(browser->mozEmbed));
+}
+
+void
+forward_clicked_cb (GtkButton *button, TestGeckoBrowser *browser)
+{
+ g_print("forward_clicked_cb\n");
+ gecko_embed_go_forward(GECKO_EMBED(browser->mozEmbed));
+}
+
+void
+reload_clicked_cb (GtkButton *button, TestGeckoBrowser *browser)
+{
+ g_print("reload_clicked_cb\n");
+ GdkModifierType state = (GdkModifierType)0;
+ gint x, y;
+ gdk_window_get_pointer(NULL, &x, &y, &state);
+
+ gecko_embed_reload(GECKO_EMBED(browser->mozEmbed),
+ (state & GDK_SHIFT_MASK) ?
+ GECKO_EMBED_FLAG_RELOADBYPASSCACHE :
+ GECKO_EMBED_FLAG_RELOADNORMAL);
+}
+
+void
+stream_clicked_cb (GtkButton *button, TestGeckoBrowser *browser)
+{
+ const char *data;
+ const char *data2;
+ data = "<html>Hi";
+ data2 = " there</html>\n";
+ g_print("stream_clicked_cb\n");
+ gecko_embed_open_stream(GECKO_EMBED(browser->mozEmbed),
+ "file://", "text/html");
+ gecko_embed_append_data(GECKO_EMBED(browser->mozEmbed),
+ data, strlen(data));
+ gecko_embed_append_data(GECKO_EMBED(browser->mozEmbed),
+ data2, strlen(data2));
+ gecko_embed_close_stream(GECKO_EMBED(browser->mozEmbed));
+}
+
+void
+url_activate_cb (GtkEditable *widget, TestGeckoBrowser *browser)
+{
+ gchar *text = gtk_editable_get_chars(widget, 0, -1);
+ g_print("loading url %s\n", text);
+ gecko_embed_load_url(GECKO_EMBED(browser->mozEmbed), text);
+ g_free(text);
+}
+
+void
+menu_open_new_cb (GtkMenuItem *menuitem, TestGeckoBrowser *browser)
+{
+ g_print("opening new browser.\n");
+ TestGeckoBrowser *newBrowser =
+ new_gecko_browser(GECKO_EMBED_FLAG_DEFAULTCHROME);
+ gtk_widget_set_usize(newBrowser->mozEmbed, 400, 400);
+ set_browser_visibility(newBrowser, TRUE);
+}
+
+void
+menu_stream_cb (GtkMenuItem *menuitem, TestGeckoBrowser *browser)
+{
+ g_print("menu_stream_cb\n");
+ const char *data;
+ const char *data2;
+ data = "<html>Hi";
+ data2 = " there</html>\n";
+ g_print("stream_clicked_cb\n");
+ gecko_embed_open_stream(GECKO_EMBED(browser->mozEmbed),
+ "file://", "text/html");
+ gecko_embed_append_data(GECKO_EMBED(browser->mozEmbed),
+ data, strlen(data));
+ gecko_embed_append_data(GECKO_EMBED(browser->mozEmbed),
+ data2, strlen(data2));
+ gecko_embed_close_stream(GECKO_EMBED(browser->mozEmbed));
+}
+
+void
+menu_close_cb (GtkMenuItem *menuitem, TestGeckoBrowser *browser)
+{
+ gtk_widget_destroy(browser->topLevelWindow);
+}
+
+void
+menu_quit_cb (GtkMenuItem *menuitem, TestGeckoBrowser *browser)
+{
+ TestGeckoBrowser *tmpBrowser;
+ GList *tmp_list = browser_list;
+ tmpBrowser = (TestGeckoBrowser *)tmp_list->data;
+ while (tmpBrowser) {
+ tmp_list = tmp_list->next;
+ gtk_widget_destroy(tmpBrowser->topLevelWindow);
+ tmpBrowser = (TestGeckoBrowser *)tmp_list->data;
+ }
+}
+
+gboolean
+delete_cb(GtkWidget *widget, GdkEventAny *event, TestGeckoBrowser *browser)
+{
+ g_print("delete_cb\n");
+ gtk_widget_destroy(widget);
+ return TRUE;
+}
+
+void
+destroy_cb (GtkWidget *widget, TestGeckoBrowser *browser)
+{
+ GList *tmp_list;
+ g_print("destroy_cb\n");
+ num_browsers--;
+ tmp_list = g_list_find(browser_list, browser);
+ browser_list = g_list_remove_link(browser_list, tmp_list);
+ if (browser->tempMessage)
+ g_free(browser->tempMessage);
+ if (num_browsers == 0)
+ gtk_main_quit();
+}
+
+void
+location_changed_cb (GeckoEmbed *embed, TestGeckoBrowser *browser)
+{
+ char *newLocation;
+ int newPosition = 0;
+ g_print("location_changed_cb\n");
+ newLocation = gecko_embed_get_location(embed);
+ if (newLocation)
+ {
+ gtk_editable_delete_text(GTK_EDITABLE(browser->urlEntry), 0, -1);
+ gtk_editable_insert_text(GTK_EDITABLE(browser->urlEntry),
+ newLocation, strlen(newLocation), &newPosition);
+ g_free(newLocation);
+ }
+ else
+ g_print("failed to get location!\n");
+ // always make sure to clear the tempMessage. it might have been
+ // set from the link before a click and we wouldn't have gotten the
+ // callback to unset it.
+ update_temp_message(browser, 0);
+ // update the nav buttons on a location change
+ update_nav_buttons(browser);
+}
+
+void
+title_changed_cb (GeckoEmbed *embed, TestGeckoBrowser *browser)
+{
+ char *newTitle;
+ g_print("title_changed_cb\n");
+ newTitle = gecko_embed_get_title(embed);
+ if (newTitle)
+ {
+ gtk_window_set_title(GTK_WINDOW(browser->topLevelWindow), newTitle);
+ g_free(newTitle);
+ }
+
+}
+
+void
+load_started_cb (GeckoEmbed *embed, TestGeckoBrowser *browser)
+{
+ g_print("load_started_cb\n");
+ gtk_widget_set_sensitive(browser->stopButton, TRUE);
+ gtk_widget_set_sensitive(browser->reloadButton, FALSE);
+ browser->loadPercent = 0;
+ browser->bytesLoaded = 0;
+ browser->maxBytesLoaded = 0;
+ update_status_bar_text(browser);
+}
+
+void
+load_finished_cb (GeckoEmbed *embed, TestGeckoBrowser *browser)
+{
+ g_print("load_finished_cb\n");
+ gtk_widget_set_sensitive(browser->stopButton, FALSE);
+ gtk_widget_set_sensitive(browser->reloadButton, TRUE);
+ browser->loadPercent = 0;
+ browser->bytesLoaded = 0;
+ browser->maxBytesLoaded = 0;
+ update_status_bar_text(browser);
+ gtk_progress_set_percentage(GTK_PROGRESS(browser->progressBar), 0);
+}
+
+
+void
+net_state_change_cb (GeckoEmbed *embed, gint flags, guint status,
+ TestGeckoBrowser *browser)
+{
+ g_print("net_state_change_cb %d\n", flags);
+ if (flags & GECKO_EMBED_FLAG_IS_REQUEST) {
+ if (flags & GECKO_EMBED_FLAG_REDIRECTING)
+ browser->statusMessage = "Redirecting to site...";
+ else if (flags & GECKO_EMBED_FLAG_TRANSFERRING)
+ browser->statusMessage = "Transferring data from site...";
+ else if (flags & GECKO_EMBED_FLAG_NEGOTIATING)
+ browser->statusMessage = "Waiting for authorization...";
+ }
+
+ if (status == GECKO_EMBED_STATUS_FAILED_DNS)
+ browser->statusMessage = "Site not found.";
+ else if (status == GECKO_EMBED_STATUS_FAILED_CONNECT)
+ browser->statusMessage = "Failed to connect to site.";
+ else if (status == GECKO_EMBED_STATUS_FAILED_TIMEOUT)
+ browser->statusMessage = "Failed due to connection timeout.";
+ else if (status == GECKO_EMBED_STATUS_FAILED_USERCANCELED)
+ browser->statusMessage = "User canceled connecting to site.";
+
+ if (flags & GECKO_EMBED_FLAG_IS_DOCUMENT) {
+ if (flags & GECKO_EMBED_FLAG_START)
+ browser->statusMessage = "Loading site...";
+ else if (flags & GECKO_EMBED_FLAG_STOP)
+ browser->statusMessage = "Done.";
+ }
+
+ update_status_bar_text(browser);
+
+}
+
+void net_state_change_all_cb (GeckoEmbed *embed, const char *uri,
+ gint flags, guint status,
+ TestGeckoBrowser *browser)
+{
+ // g_print("net_state_change_all_cb %s %d %d\n", uri, flags, status);
+}
+
+void progress_change_cb (GeckoEmbed *embed, gint cur, gint max,
+ TestGeckoBrowser *browser)
+{
+ g_print("progress_change_cb cur %d max %d\n", cur, max);
+
+ // avoid those pesky divide by zero errors
+ if (max < 1)
+ {
+ gtk_progress_set_activity_mode(GTK_PROGRESS(browser->progressBar), FALSE);
+ browser->loadPercent = 0;
+ browser->bytesLoaded = cur;
+ browser->maxBytesLoaded = 0;
+ update_status_bar_text(browser);
+ }
+ else
+ {
+ browser->bytesLoaded = cur;
+ browser->maxBytesLoaded = max;
+ if (cur > max)
+ browser->loadPercent = 100;
+ else
+ browser->loadPercent = (cur * 100) / max;
+ update_status_bar_text(browser);
+ gtk_progress_set_percentage(GTK_PROGRESS(browser->progressBar), browser->loadPercent / 100.0);
+ }
+
+}
+
+void progress_change_all_cb (GeckoEmbed *embed, const char *uri,
+ gint cur, gint max,
+ TestGeckoBrowser *browser)
+{
+ //g_print("progress_change_all_cb %s cur %d max %d\n", uri, cur, max);
+}
+
+void
+link_message_cb (GeckoEmbed *embed, TestGeckoBrowser *browser)
+{
+ char *message;
+ g_print("link_message_cb\n");
+ message = gecko_embed_get_link_message(embed);
+ if (!message || !*message)
+ update_temp_message(browser, 0);
+ else
+ update_temp_message(browser, message);
+ if (message)
+ g_free(message);
+}
+
+void
+js_status_cb (GeckoEmbed *embed, TestGeckoBrowser *browser)
+{
+ char *message;
+ g_print("js_status_cb\n");
+ message = gecko_embed_get_js_status(embed);
+ if (!message || !*message)
+ update_temp_message(browser, 0);
+ else
+ update_temp_message(browser, message);
+ if (message)
+ g_free(message);
+}
+
+void
+new_window_cb (GeckoEmbed *embed, GeckoEmbed **newEmbed, guint chromemask, TestGeckoBrowser *browser)
+{
+ g_print("new_window_cb\n");
+ g_print("embed is %p chromemask is %d\n", (void *)embed, chromemask);
+ TestGeckoBrowser *newBrowser = new_gecko_browser(chromemask);
+ gtk_widget_set_usize(newBrowser->mozEmbed, 400, 400);
+ *newEmbed = GECKO_EMBED(newBrowser->mozEmbed);
+ g_print("new browser is %p\n", (void *)*newEmbed);
+}
+
+void
+visibility_cb (GeckoEmbed *embed, gboolean visibility, TestGeckoBrowser *browser)
+{
+ g_print("visibility_cb %d\n", visibility);
+ set_browser_visibility(browser, visibility);
+}
+
+void
+destroy_brsr_cb (GeckoEmbed *embed, TestGeckoBrowser *browser)
+{
+ g_print("destroy_brsr_cb\n");
+ gtk_widget_destroy(browser->topLevelWindow);
+}
+
+gint
+open_uri_cb (GeckoEmbed *embed, const char *uri, TestGeckoBrowser *browser)
+{
+ g_print("open_uri_cb %s\n", uri);
+
+ // interrupt this test load
+ if (!strcmp(uri, "http://people.redhat.com/blizzard/monkeys.txt"))
+ return TRUE;
+ // don't interrupt anything
+ return FALSE;
+}
+
+void
+size_to_cb (GeckoEmbed *embed, gint width, gint height,
+ TestGeckoBrowser *browser)
+{
+ g_print("*** size_to_cb %d %d\n", width, height);
+ gtk_widget_set_usize(browser->mozEmbed, width, height);
+}
+
+gboolean dom_key_down_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ nsIDOMEvent *domevent = gecko_dom_event_get_I (gecko_event);
+ nsCOMPtr<nsIDOMKeyEvent> event (do_QueryInterface (domevent));
+
+ PRUint32 keyCode = 0;
+ // g_print("dom_key_down_cb\n");
+ event->GetKeyCode(&keyCode);
+ // g_print("key code is %d\n", keyCode);
+ return NS_OK;
+}
+
+gboolean dom_key_press_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ nsIDOMEvent *domevent = gecko_dom_event_get_I (gecko_event);
+ nsCOMPtr<nsIDOMKeyEvent> event (do_QueryInterface (domevent));
+
+ PRUint32 keyCode = 0;
+ // g_print("dom_key_press_cb\n");
+ event->GetCharCode(&keyCode);
+ // g_print("char code is %d\n", keyCode);
+ return NS_OK;
+}
+
+gboolean dom_key_up_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ nsIDOMEvent *domevent = gecko_dom_event_get_I (gecko_event);
+ nsCOMPtr<nsIDOMKeyEvent> event (do_QueryInterface (domevent));
+
+ PRUint32 keyCode = 0;
+ // g_print("dom_key_up_cb\n");
+ event->GetKeyCode(&keyCode);
+ // g_print("key code is %d\n", keyCode);
+ return NS_OK;
+}
+
+gboolean dom_mouse_down_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ // g_print("dom_mouse_down_cb\n");
+ return NS_OK;
+ }
+
+gboolean dom_mouse_up_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ // g_print("dom_mouse_up_cb\n");
+ return NS_OK;
+}
+
+gboolean dom_mouse_click_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ nsIDOMEvent *domevent = gecko_dom_event_get_I (gecko_event);
+ nsCOMPtr<nsIDOMMouseEvent> event (do_QueryInterface (domevent));
+
+ // g_print("dom_mouse_click_cb\n");
+ PRUint16 button;
+ event->GetButton(&button);
+ printf("button was %d\n", button);
+ return NS_OK;
+}
+
+gboolean dom_mouse_dbl_click_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ // g_print("dom_mouse_dbl_click_cb\n");
+ return NS_OK;
+}
+
+gboolean dom_mouse_over_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ //g_print("dom_mouse_over_cb\n");
+ return NS_OK;
+}
+
+gboolean dom_mouse_out_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ //g_print("dom_mouse_out_cb\n");
+ return NS_OK;
+}
+
+gboolean dom_activate_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ //g_print("dom_activate_cb\n");
+ return NS_OK;
+}
+
+gboolean dom_focus_in_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ //g_print("dom_focus_in_cb\n");
+ return NS_OK;
+}
+
+gboolean dom_focus_out_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ //g_print("dom_focus_out_cb\n");
+ return NS_OK;
+}
+
+gboolean dom_context_menu_cb (GeckoEmbed *embed,
+ GeckoDOMEvent *gecko_event,
+ TestGeckoBrowser *browser)
+{
+ g_print("dom_context_menu_cb\n");
+ return NS_OK;
+}
+
+void new_window_orphan_cb (GeckoEmbedSingle *embed,
+ GeckoEmbed **retval, guint chromemask,
+ gpointer data)
+{
+ g_print("new_window_orphan_cb\n");
+ g_print("chromemask is %d\n", chromemask);
+ TestGeckoBrowser *newBrowser = new_gecko_browser(chromemask);
+ *retval = GECKO_EMBED(newBrowser->mozEmbed);
+ g_print("new browser is %p\n", (void *)*retval);
+}
+
+// utility functions
+
+void
+update_status_bar_text(TestGeckoBrowser *browser)
+{
+ gchar message[256];
+
+ gtk_statusbar_pop(GTK_STATUSBAR(browser->statusBar), 1);
+ if (browser->tempMessage)
+ gtk_statusbar_push(GTK_STATUSBAR(browser->statusBar), 1, browser->tempMessage);
+ else
+ {
+ if (browser->loadPercent)
+ {
+ g_snprintf(message, 255, "%s (%d%% complete, %d bytes of %d loaded)", browser->statusMessage, browser->loadPercent, browser->bytesLoaded, browser->maxBytesLoaded);
+ }
+ else if (browser->bytesLoaded)
+ {
+ g_snprintf(message, 255, "%s (%d bytes loaded)", browser->statusMessage, browser->bytesLoaded);
+ }
+ else if (browser->statusMessage == NULL)
+ {
+ g_snprintf(message, 255, " ");
+ }
+ else
+ {
+ g_snprintf(message, 255, "%s", browser->statusMessage);
+ }
+ gtk_statusbar_push(GTK_STATUSBAR(browser->statusBar), 1, message);
+ }
+}
+
+void
+update_temp_message(TestGeckoBrowser *browser, const char *message)
+{
+ if (browser->tempMessage)
+ g_free(browser->tempMessage);
+ if (message)
+ browser->tempMessage = g_strdup(message);
+ else
+ browser->tempMessage = 0;
+ // now that we've updated the temp message, redraw the status bar
+ update_status_bar_text(browser);
+}
+
+
+void
+update_nav_buttons (TestGeckoBrowser *browser)
+{
+ gboolean can_go_back;
+ gboolean can_go_forward;
+ can_go_back = gecko_embed_can_go_back(GECKO_EMBED(browser->mozEmbed));
+ can_go_forward = gecko_embed_can_go_forward(GECKO_EMBED(browser->mozEmbed));
+ if (can_go_back)
+ gtk_widget_set_sensitive(browser->backButton, TRUE);
+ else
+ gtk_widget_set_sensitive(browser->backButton, FALSE);
+ if (can_go_forward)
+ gtk_widget_set_sensitive(browser->forwardButton, TRUE);
+ else
+ gtk_widget_set_sensitive(browser->forwardButton, FALSE);
+ }