Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/browser/sugar-browser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'browser/sugar-browser.cpp')
-rw-r--r--browser/sugar-browser.cpp938
1 files changed, 938 insertions, 0 deletions
diff --git a/browser/sugar-browser.cpp b/browser/sugar-browser.cpp
new file mode 100644
index 0000000..cd455b6
--- /dev/null
+++ b/browser/sugar-browser.cpp
@@ -0,0 +1,938 @@
+/*
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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 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.
+ */
+
+#include <config.h>
+
+#include "sugar-browser.h"
+#include "sugar-marshal.h"
+#include "GeckoContentHandler.h"
+#include "GeckoDownload.h"
+
+#include <gdk/gdkx.h>
+#include <gtkmozembed_internal.h>
+#include <nsCOMPtr.h>
+#include <nsIPrefService.h>
+#include <nsServiceManagerUtils.h>
+#include <nsStringAPI.h>
+#include <nsILocalFile.h>
+#include <nsIWebBrowser.h>
+#include <nsIWebBrowserFocus.h>
+#include <nsIWebBrowserPersist.h>
+#include <nsIDOMWindow.h>
+#include <nsIDOMWindowUtils.h>
+#include <nsIDOMDocument.h>
+#include <nsIDOMMouseEvent.h>
+#include <nsIGenericFactory.h>
+#include <nsIHelperAppLauncherDialog.h>
+#include <nsIComponentRegistrar.h>
+#include <nsIDOMNode.h>
+#include <nsIDOMEventTarget.h>
+#include <nsIDOMHTMLImageElement.h>
+#include <nsIIOService.h>
+#include <nsComponentManagerUtils.h>
+#include <imgICache.h>
+#include <nsIProperties.h>
+#include <nsIWebNavigation.h>
+#include <nsISupportsPrimitives.h>
+#include <nsIInterfaceRequestorUtils.h>
+#include <nsIMIMEHeaderParam.h>
+#include <nsISHistory.h>
+#include <nsIHistoryEntry.h>
+#include <nsISHEntry.h>
+#include <nsIInputStream.h>
+
+enum {
+ PROP_0,
+ PROP_PROGRESS,
+ PROP_TITLE,
+ PROP_ADDRESS,
+ PROP_CAN_GO_BACK,
+ PROP_CAN_GO_FORWARD,
+ PROP_LOADING,
+ PROP_DOCUMENT_METADATA
+};
+
+enum {
+ MOUSE_CLICK,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS];
+
+static const nsModuleComponentInfo sSugarComponents[] = {
+ {
+ "Gecko Content Handler",
+ GECKOCONTENTHANDLER_CID,
+ NS_IHELPERAPPLAUNCHERDLG_CONTRACTID,
+ NULL
+ },
+ {
+ "Gecko Download",
+ GECKODOWNLOAD_CID,
+ NS_TRANSFER_CONTRACTID,
+ NULL
+ }
+};
+
+int (*old_handler) (Display *, XErrorEvent *);
+
+static int
+error_handler (Display *d, XErrorEvent *e)
+{
+ gchar buf[64];
+ gchar *msg;
+
+ XGetErrorText(d, e->error_code, buf, 63);
+
+ msg =
+ g_strdup_printf("The program '%s' received an X Window System error.\n"
+ "This probably reflects a bug in the program.\n"
+ "The error was '%s'.\n"
+ " (Details: serial %ld error_code %d request_code %d minor_code %d)\n",
+ g_get_prgname (),
+ buf,
+ e->serial,
+ e->error_code,
+ e->request_code,
+ e->minor_code);
+
+ g_warning ("%s", msg);
+
+ return 0;
+ /*return (*old_handler)(d, e);*/
+}
+
+static void
+setup_plugin_path ()
+{
+ const char *user_path;
+ char *new_path;
+
+ user_path = g_getenv ("MOZ_PLUGIN_PATH");
+ new_path = g_strconcat (user_path ? user_path : "",
+ user_path ? ":" : "",
+ PLUGIN_DIR,
+ (char *) NULL);
+ g_setenv ("MOZ_PLUGIN_PATH", new_path, TRUE);
+ g_free (new_path);
+}
+
+gboolean
+sugar_browser_startup(const char *profile_path, const char *profile_name)
+{
+ nsresult rv;
+
+ setup_plugin_path();
+
+ gtk_moz_embed_set_profile_path(profile_path, profile_name);
+
+ old_handler = XSetErrorHandler(error_handler);
+
+ gtk_moz_embed_push_startup();
+
+ nsCOMPtr<nsIPrefService> prefService;
+ prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
+ NS_ENSURE_TRUE(prefService, FALSE);
+
+ /* Read our predefined default prefs */
+ nsCOMPtr<nsILocalFile> file;
+ NS_NewNativeLocalFile(nsCString(SHARE_DIR"/gecko-prefs.js"),
+ PR_TRUE, getter_AddRefs(file));
+ NS_ENSURE_TRUE(file, 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);
+
+ pref->SetCharPref ("helpers.private_mime_types_file", SHARE_DIR"/mime.types");
+
+ rv = prefService->ReadUserPrefs (nsnull);
+ if (NS_FAILED(rv)) {
+ g_warning ("failed to read user preferences, error: %x", rv);
+ }
+
+ nsCOMPtr<nsIComponentRegistrar> componentRegistrar;
+ NS_GetComponentRegistrar(getter_AddRefs(componentRegistrar));
+ NS_ENSURE_TRUE (componentRegistrar, FALSE);
+
+ nsCOMPtr<nsIFactory> contentHandlerFactory;
+ rv = NS_NewGeckoContentHandlerFactory(getter_AddRefs(contentHandlerFactory));
+ rv = componentRegistrar->RegisterFactory(sSugarComponents[0].mCID,
+ sSugarComponents[0].mDescription,
+ sSugarComponents[0].mContractID,
+ contentHandlerFactory);
+ if (NS_FAILED(rv)) {
+ g_warning ("Failed to register factory for %s\n", sSugarComponents[0].mDescription);
+ return FALSE;
+ }
+
+ nsCOMPtr<nsIFactory> downloadFactory;
+ rv = NS_NewGeckoDownloadFactory(getter_AddRefs(downloadFactory));
+ rv = componentRegistrar->RegisterFactory(sSugarComponents[1].mCID,
+ sSugarComponents[1].mDescription,
+ sSugarComponents[1].mContractID,
+ downloadFactory);
+ if (NS_FAILED(rv)) {
+ g_warning ("Failed to register factory for %s\n", sSugarComponents[1].mDescription);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+sugar_browser_shutdown(void)
+{
+ gtk_moz_embed_pop_startup();
+}
+
+G_DEFINE_TYPE(SugarBrowser, sugar_browser, GTK_TYPE_MOZ_EMBED)
+
+static nsresult
+NewURI(const char *uri, nsIURI **result)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager (getter_AddRefs (mgr));
+ NS_ENSURE_TRUE(mgr, FALSE);
+
+ nsCOMPtr<nsIIOService> ioService;
+ rv = mgr->GetServiceByContractID ("@mozilla.org/network/io-service;1",
+ NS_GET_IID (nsIIOService),
+ getter_AddRefs(ioService));
+ NS_ENSURE_SUCCESS(rv, FALSE);
+
+ nsCString cSpec(uri);
+ return ioService->NewURI (cSpec, nsnull, nsnull, result);
+}
+
+static nsresult
+FilenameFromContentDisposition(nsCString contentDisposition, nsCString &fileName)
+{
+ nsresult rv;
+
+ nsCString fallbackCharset;
+
+ nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
+ do_GetService("@mozilla.org/network/mime-hdrparam;1");
+ NS_ENSURE_TRUE(mimehdrpar, NS_ERROR_FAILURE);
+
+ nsString aFileName;
+ rv = mimehdrpar->GetParameter (contentDisposition, "filename",
+ fallbackCharset, PR_TRUE, nsnull,
+ aFileName);
+
+ if (NS_FAILED(rv) || !fileName.Length()) {
+ rv = mimehdrpar->GetParameter (contentDisposition, "name",
+ fallbackCharset, PR_TRUE, nsnull,
+ aFileName);
+ }
+
+ if (NS_SUCCEEDED(rv) && fileName.Length()) {
+ NS_UTF16ToCString (aFileName, NS_CSTRING_ENCODING_UTF8, fileName);
+ }
+
+ return NS_OK;
+}
+
+static nsresult
+ImageNameFromCache(nsIURI *imgURI, nsCString &imgName)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager (getter_AddRefs (mgr));
+ NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE);
+
+ nsCOMPtr<imgICache> imgCache;
+ rv = mgr->GetServiceByContractID("@mozilla.org/image/cache;1",
+ NS_GET_IID (imgICache),
+ getter_AddRefs(imgCache));
+ NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIProperties> imgProperties;
+ imgCache->FindEntryProperties(imgURI, getter_AddRefs(imgProperties));
+ if (imgProperties) {
+ nsCOMPtr<nsISupportsCString> dispositionCString;
+ imgProperties->Get("content-disposition",
+ NS_GET_IID(nsISupportsCString),
+ getter_AddRefs(dispositionCString));
+ if (dispositionCString) {
+ nsCString contentDisposition;
+ dispositionCString->GetData(contentDisposition);
+ FilenameFromContentDisposition(contentDisposition, imgName);
+ }
+ }
+
+ return NS_OK;
+}
+
+static SugarBrowserMetadata *
+sugar_browser_get_document_metadata(SugarBrowser *browser)
+{
+ SugarBrowserMetadata *metadata = sugar_browser_metadata_new();
+
+#ifdef HAVE_NS_WEB_BROWSER
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser),
+ getter_AddRefs(webBrowser));
+ NS_ENSURE_TRUE(webBrowser, metadata);
+
+ nsCOMPtr<nsIDOMWindow> DOMWindow;
+ webBrowser->GetContentDOMWindow(getter_AddRefs(DOMWindow));
+ NS_ENSURE_TRUE(DOMWindow, metadata);
+
+ nsCOMPtr<nsIDOMWindowUtils> DOMWindowUtils(do_GetInterface(DOMWindow));
+ NS_ENSURE_TRUE(DOMWindowUtils, metadata);
+
+ const PRUnichar contentDispositionLiteral[] =
+ {'c', 'o', 'n', 't', 'e', 'n', 't', '-', 'd', 'i', 's', 'p',
+ 'o', 's', 'i', 't', 'i', 'o', 'n', '\0'};
+
+ nsString contentDisposition;
+ DOMWindowUtils->GetDocumentMetadata(nsString(contentDispositionLiteral),
+ contentDisposition);
+
+ nsCString cContentDisposition;
+ NS_UTF16ToCString (contentDisposition, NS_CSTRING_ENCODING_UTF8,
+ cContentDisposition);
+
+ nsCString fileName;
+ FilenameFromContentDisposition(cContentDisposition, fileName);
+
+ if (!fileName.Length()) {
+ nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(webBrowser));
+ if (webNav) {
+ nsCOMPtr<nsIURI> docURI;
+ webNav->GetCurrentURI (getter_AddRefs(docURI));
+
+ nsCOMPtr<nsIURL> url(do_QueryInterface(docURI));
+ if (url) {
+ url->GetFileName(fileName);
+ }
+ }
+ }
+
+ if (fileName.Length()) {
+ metadata->filename = g_strdup(fileName.get());
+ }
+#endif
+
+ return metadata;
+}
+
+static void
+sugar_browser_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SugarBrowser *browser = SUGAR_BROWSER(object);
+
+ switch (prop_id) {
+ case PROP_PROGRESS:
+ g_value_set_double(value, browser->progress);
+ break;
+ case PROP_ADDRESS:
+ g_value_set_string(value, browser->address);
+ break;
+ case PROP_TITLE:
+ g_value_set_string(value, browser->title);
+ break;
+ case PROP_CAN_GO_BACK:
+ g_value_set_boolean(value, browser->can_go_back);
+ break;
+ case PROP_CAN_GO_FORWARD:
+ g_value_set_boolean(value, browser->can_go_forward);
+ break;
+ case PROP_LOADING:
+ g_value_set_boolean(value, browser->loading);
+ break;
+ case PROP_DOCUMENT_METADATA:
+ SugarBrowserMetadata *metadata;
+ metadata = sugar_browser_get_document_metadata(browser);
+ g_value_set_boxed(value, metadata);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+sugar_browser_class_init(SugarBrowserClass *browser_class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(browser_class);
+
+ gobject_class->get_property = sugar_browser_get_property;
+
+ signals[MOUSE_CLICK] = g_signal_new ("mouse_click",
+ SUGAR_TYPE_BROWSER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(SugarBrowser, mouse_click),
+ g_signal_accumulator_true_handled, NULL,
+ sugar_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN,
+ 1,
+ SUGAR_TYPE_BROWSER_EVENT);
+
+ g_object_class_install_property(gobject_class, PROP_PROGRESS,
+ g_param_spec_double ("progress",
+ "Progress",
+ "Progress",
+ 0.0, 1.0, 0.0,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_ADDRESS,
+ g_param_spec_string ("address",
+ "Address",
+ "Address",
+ "",
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_TITLE,
+ g_param_spec_string ("title",
+ "Title",
+ "Title",
+ "",
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_CAN_GO_BACK,
+ g_param_spec_boolean ("can-go-back",
+ "Can go back",
+ "Can go back",
+ FALSE,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_CAN_GO_FORWARD,
+ g_param_spec_boolean ("can-go-forward",
+ "Can go forward",
+ "Can go forward",
+ FALSE,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_LOADING,
+ g_param_spec_boolean ("loading",
+ "Loading",
+ "Loading",
+ FALSE,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property(gobject_class, PROP_DOCUMENT_METADATA,
+ g_param_spec_boxed("document-metadata",
+ "Document Metadata",
+ "Document metadata",
+ SUGAR_TYPE_BROWSER_METADATA,
+ G_PARAM_READABLE));
+
+}
+
+SugarBrowser *
+sugar_browser_create_window(SugarBrowser *browser)
+{
+ return SUGAR_BROWSER_GET_CLASS(browser)->create_window(browser);
+}
+
+static void
+update_navigation_properties(SugarBrowser *browser)
+{
+ GtkMozEmbed *embed = GTK_MOZ_EMBED(browser);
+ gboolean can_go_back;
+ gboolean can_go_forward;
+
+ can_go_back = gtk_moz_embed_can_go_back(embed);
+ if (can_go_back != browser->can_go_back) {
+ browser->can_go_back = can_go_back;
+ g_object_notify (G_OBJECT(browser), "can-go-back");
+ }
+
+ can_go_forward = gtk_moz_embed_can_go_forward(embed);
+ if (can_go_forward != browser->can_go_forward) {
+ browser->can_go_forward = can_go_forward;
+ g_object_notify (G_OBJECT(browser), "can-go-forward");
+ }
+}
+
+static void
+new_window_cb(GtkMozEmbed *embed,
+ GtkMozEmbed **newEmbed,
+ guint chromemask)
+{
+ SugarBrowser *browser;
+
+ browser = sugar_browser_create_window(SUGAR_BROWSER(embed));
+
+ *newEmbed = GTK_MOZ_EMBED(browser);
+}
+
+static void
+sugar_browser_set_progress(SugarBrowser *browser, float progress)
+{
+ g_return_if_fail(SUGAR_IS_BROWSER(browser));
+
+ browser->progress = progress;
+ g_object_notify (G_OBJECT(browser), "progress");
+}
+
+static void
+sugar_browser_set_loading(SugarBrowser *browser, gboolean loading)
+{
+ g_return_if_fail(SUGAR_IS_BROWSER(browser));
+
+ browser->loading = loading;
+ g_object_notify (G_OBJECT(browser), "loading");
+}
+
+static void
+net_state_cb(GtkMozEmbed *embed, const char *aURI, gint state, guint status)
+{
+ SugarBrowser *browser = SUGAR_BROWSER(embed);
+
+ if (state & GTK_MOZ_EMBED_FLAG_IS_NETWORK) {
+ if (state & GTK_MOZ_EMBED_FLAG_START) {
+ browser->total_requests = 0;
+ browser->current_requests = 0;
+
+ sugar_browser_set_progress(browser, 0.03);
+ sugar_browser_set_loading(browser, TRUE);
+ update_navigation_properties(browser);
+ } else if (state & GTK_MOZ_EMBED_FLAG_STOP) {
+ sugar_browser_set_progress(browser, 1.0);
+ sugar_browser_set_loading(browser, FALSE);
+ update_navigation_properties(browser);
+ }
+ }
+
+ if (state & GTK_MOZ_EMBED_FLAG_IS_REQUEST) {
+ float progress;
+
+ if (state & GTK_MOZ_EMBED_FLAG_START) {
+ browser->total_requests++;
+ }
+ else if (state & GTK_MOZ_EMBED_FLAG_STOP)
+ {
+ browser->current_requests++;
+ }
+
+ progress = float(browser->current_requests) /
+ float(browser->total_requests);
+ if (progress > browser->progress) {
+ sugar_browser_set_progress(browser, progress);
+ }
+ }
+}
+
+static void
+title_cb(GtkMozEmbed *embed)
+{
+ SugarBrowser *browser = SUGAR_BROWSER(embed);
+
+ g_free(browser->title);
+ browser->title = gtk_moz_embed_get_title(embed);
+
+ g_object_notify (G_OBJECT(browser), "title");
+}
+
+static void
+location_cb(GtkMozEmbed *embed)
+{
+ SugarBrowser *browser = SUGAR_BROWSER(embed);
+
+ g_free(browser->address);
+ browser->address = gtk_moz_embed_get_location(embed);
+
+ g_object_notify (G_OBJECT(browser), "address");
+
+ update_navigation_properties(browser);
+}
+
+static char *
+get_image_name(const char *uri)
+{
+ nsresult rv;
+
+ nsCString imgName;
+
+ nsCOMPtr<nsIURI> imgURI;
+ rv = NewURI(uri, getter_AddRefs(imgURI));
+ NS_ENSURE_SUCCESS(rv, NULL);
+
+ ImageNameFromCache(imgURI, imgName);
+
+ if (!imgName.Length()) {
+ nsCOMPtr<nsIURL> url(do_QueryInterface(imgURI));
+ if (url) {
+ url->GetFileName(imgName);
+ }
+ }
+
+ return imgName.Length() ? g_strdup(imgName.get()) : NULL;
+}
+
+static gboolean
+dom_mouse_click_cb(GtkMozEmbed *embed, nsIDOMMouseEvent *mouseEvent)
+{
+ SugarBrowser *browser = SUGAR_BROWSER(embed);
+ SugarBrowserEvent *event;
+ gint return_value = FALSE;
+
+ nsCOMPtr<nsIDOMEventTarget> eventTarget;
+ mouseEvent->GetTarget(getter_AddRefs(eventTarget));
+ NS_ENSURE_TRUE(mouseEvent, FALSE);
+
+ nsCOMPtr<nsIDOMNode> targetNode;
+ targetNode = do_QueryInterface(eventTarget);
+ NS_ENSURE_TRUE(targetNode, FALSE);
+
+ event = sugar_browser_event_new();
+
+ nsresult rv;
+
+ PRUint16 type;
+ rv = targetNode->GetNodeType(&type);
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(targetNode);
+ 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;
+ image = do_QueryInterface(targetNode, &rv);
+ if (NS_FAILED(rv) || !image) return NS_ERROR_FAILURE;
+
+ rv = image->GetSrc(img);
+ if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+ nsCString cImg;
+ NS_UTF16ToCString (img, NS_CSTRING_ENCODING_UTF8, cImg);
+ event->image_uri = g_strdup(cImg.get());
+ event->image_name = get_image_name(event->image_uri);
+ }
+ }
+
+ PRUint16 btn = 0;
+ mouseEvent->GetButton (&btn);
+ event->button = btn + 1;
+
+ g_signal_emit(browser, signals[MOUSE_CLICK], 0, event, &return_value);
+
+ sugar_browser_event_free(event);
+
+ return return_value;
+}
+
+static void
+sugar_browser_init(SugarBrowser *browser)
+{
+ browser->title = NULL;
+ browser->address = NULL;
+ browser->progress = 0.0;
+
+ g_signal_connect(G_OBJECT(browser), "new-window",
+ G_CALLBACK(new_window_cb), NULL);
+ g_signal_connect(G_OBJECT(browser), "net-state-all",
+ G_CALLBACK(net_state_cb), NULL);
+ g_signal_connect(G_OBJECT(browser), "title",
+ G_CALLBACK(title_cb), NULL);
+ g_signal_connect(G_OBJECT(browser), "location",
+ G_CALLBACK(location_cb), NULL);
+ g_signal_connect(G_OBJECT(browser), "dom-mouse-click",
+ G_CALLBACK(dom_mouse_click_cb), NULL);
+}
+
+void
+sugar_browser_scroll_pixels(SugarBrowser *browser,
+ int dx,
+ int dy)
+{
+#ifndef HAVE_GECKO_1_9
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ gtk_moz_embed_get_nsIWebBrowser (GTK_MOZ_EMBED(browser),
+ getter_AddRefs(webBrowser));
+ NS_ENSURE_TRUE (webBrowser, );
+
+ nsCOMPtr<nsIWebBrowserFocus> webBrowserFocus;
+ webBrowserFocus = do_QueryInterface (webBrowser);
+ NS_ENSURE_TRUE (webBrowserFocus, );
+
+ nsCOMPtr<nsIDOMWindow> DOMWindow;
+ webBrowserFocus->GetFocusedWindow (getter_AddRefs(DOMWindow));
+ if (!DOMWindow) {
+ webBrowser->GetContentDOMWindow (getter_AddRefs(DOMWindow));
+ }
+ NS_ENSURE_TRUE (DOMWindow, );
+
+ DOMWindow->ScrollBy (dx, dy);
+#endif
+}
+
+void
+sugar_browser_grab_focus(SugarBrowser *browser)
+{
+ GtkWidget *child;
+
+ child = gtk_bin_get_child(GTK_BIN(browser));
+
+ if (child != NULL) {
+ gtk_widget_grab_focus (child);
+ } else {
+ g_warning ("Need to realize the embed before grabbing focus!\n");
+ }
+}
+
+
+static nsresult
+GetPostData(SugarBrowser *browser, nsIInputStream **postData)
+{
+#ifdef HAVE_NS_WEB_BROWSER
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser),
+ getter_AddRefs(webBrowser));
+ NS_ENSURE_TRUE(webBrowser, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(webBrowser));
+ NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
+
+ PRInt32 sindex;
+
+ nsCOMPtr<nsISHistory> sessionHistory;
+ webNav->GetSessionHistory(getter_AddRefs(sessionHistory));
+ NS_ENSURE_TRUE(sessionHistory, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIHistoryEntry> entry;
+ sessionHistory->GetIndex(&sindex);
+ sessionHistory->GetEntryAtIndex(sindex, PR_FALSE, getter_AddRefs(entry));
+
+ nsCOMPtr<nsISHEntry> shEntry(do_QueryInterface(entry));
+ if (shEntry) {
+ shEntry->GetPostData(postData);
+ }
+
+ return NS_OK;
+#endif
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+gboolean
+sugar_browser_save_uri(SugarBrowser *browser,
+ const char *uri,
+ const char *filename)
+{
+#ifdef HAVE_NS_WEB_BROWSER
+ nsresult rv;
+
+ nsCOMPtr<nsIURI> sourceURI;
+ rv = NewURI(uri, getter_AddRefs(sourceURI));
+ NS_ENSURE_SUCCESS(rv, FALSE);
+
+ nsCOMPtr<nsILocalFile> destFile = do_CreateInstance("@mozilla.org/file/local;1");
+ NS_ENSURE_TRUE(destFile, FALSE);
+
+ destFile->InitWithNativePath(nsCString(filename));
+
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser),
+ getter_AddRefs(webBrowser));
+ NS_ENSURE_TRUE(webBrowser, FALSE);
+
+ nsCOMPtr<nsIWebBrowserPersist> webPersist = do_QueryInterface (webBrowser);
+ NS_ENSURE_TRUE(webPersist, FALSE);
+
+ nsCOMPtr<nsIInputStream> postData;
+ GetPostData(browser, getter_AddRefs(postData));
+
+ rv = webPersist->SaveURI(sourceURI, nsnull, nsnull, postData, nsnull, destFile);
+ NS_ENSURE_SUCCESS(rv, FALSE);
+
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+gboolean
+sugar_browser_save_document(SugarBrowser *browser,
+ const char *filename)
+{
+#ifdef HAVE_NS_WEB_BROWSER
+ nsresult rv;
+
+ nsCString cFile(filename);
+
+ nsCOMPtr<nsILocalFile> destFile = do_CreateInstance("@mozilla.org/file/local;1");
+ NS_ENSURE_TRUE(destFile, FALSE);
+
+ destFile->InitWithNativePath(cFile);
+
+ GString *path = g_string_new (filename);
+ char *dot_pos = strchr (path->str, '.');
+ if (dot_pos) {
+ g_string_truncate (path, dot_pos - path->str);
+ }
+ g_string_append (path, " Files");
+
+ nsCOMPtr<nsILocalFile> filesFolder;
+ filesFolder = do_CreateInstance ("@mozilla.org/file/local;1");
+ filesFolder->InitWithNativePath (nsCString(path->str));
+
+ g_string_free (path, TRUE);
+
+ nsCOMPtr<nsIWebBrowser> webBrowser;
+ gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser),
+ getter_AddRefs(webBrowser));
+ NS_ENSURE_TRUE(webBrowser, FALSE);
+
+ nsCOMPtr<nsIDOMWindow> DOMWindow;
+ webBrowser->GetContentDOMWindow(getter_AddRefs(DOMWindow));
+ NS_ENSURE_TRUE(DOMWindow, FALSE);
+
+ nsCOMPtr<nsIDOMDocument> DOMDocument;
+ DOMWindow->GetDocument (getter_AddRefs(DOMDocument));
+ NS_ENSURE_TRUE(DOMDocument, FALSE);
+
+ nsCOMPtr<nsIWebBrowserPersist> webPersist = do_QueryInterface (webBrowser);
+ NS_ENSURE_TRUE(webPersist, FALSE);
+
+ rv = webPersist->SaveDocument(DOMDocument, destFile, filesFolder, nsnull, 0, 0);
+ NS_ENSURE_SUCCESS(rv, FALSE);
+
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+GType
+sugar_browser_event_get_type(void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY(type == 0)) {
+ type = g_boxed_type_register_static("SugarBrowserEvent",
+ (GBoxedCopyFunc)sugar_browser_event_copy,
+ (GBoxedFreeFunc)sugar_browser_event_free);
+ }
+
+ return type;
+}
+
+SugarBrowserEvent *
+sugar_browser_event_new(void)
+{
+ SugarBrowserEvent *event;
+
+ event = g_new0(SugarBrowserEvent, 1);
+
+ return event;
+}
+
+SugarBrowserEvent *
+sugar_browser_event_copy(SugarBrowserEvent *event)
+{
+ SugarBrowserEvent *copy;
+
+ g_return_val_if_fail(event != NULL, NULL);
+
+ copy = g_new0(SugarBrowserEvent, 1);
+ copy->button = event->button;
+ copy->image_uri = g_strdup(event->image_uri);
+ copy->image_name = g_strdup(event->image_name);
+
+ return copy;
+}
+
+void
+sugar_browser_event_free(SugarBrowserEvent *event)
+{
+ g_return_if_fail(event != NULL);
+
+ if (event->image_uri) {
+ g_free(event->image_uri);
+ }
+ if (event->image_name) {
+ g_free(event->image_name);
+ }
+
+ g_free(event);
+}
+
+GType
+sugar_browser_metadata_get_type(void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY(type == 0)) {
+ type = g_boxed_type_register_static("SugarBrowserMetadata",
+ (GBoxedCopyFunc)sugar_browser_metadata_copy,
+ (GBoxedFreeFunc)sugar_browser_metadata_free);
+ }
+
+ return type;
+}
+
+SugarBrowserMetadata *
+sugar_browser_metadata_new(void)
+{
+ SugarBrowserMetadata *metadata;
+
+ metadata = g_new0(SugarBrowserMetadata, 1);
+
+ return metadata;
+}
+
+SugarBrowserMetadata *
+sugar_browser_metadata_copy(SugarBrowserMetadata *metadata)
+{
+ SugarBrowserMetadata *copy;
+
+ g_return_val_if_fail(metadata != NULL, NULL);
+
+ copy = g_new0(SugarBrowserMetadata, 1);
+ copy->filename = g_strdup(metadata->filename);
+
+ return copy;
+}
+
+void
+sugar_browser_metadata_free(SugarBrowserMetadata *metadata)
+{
+ g_return_if_fail(metadata != NULL);
+
+ if (metadata->filename) {
+ g_free(metadata->filename);
+ }
+
+ g_free(metadata);
+}