/* * Copyright (C) 2001 Philip Langdale * Copyright (C) 2003 Marco Pesenti Gritti * Copyright (C) 2003 Xan Lopez * Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * $Id$ */ #include "mozilla-config.h" #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ephy-prefs.h" #include "ephy-embed-single.h" #include "ephy-embed-shell.h" #include "ephy-file-chooser.h" #include "ephy-stock-icons.h" #include "ephy-gui.h" #include "ephy-debug.h" #include "eel-gconf-extensions.h" #include "ContentHandler.h" #include "MozDownload.h" #include "EphyUtils.h" class GContentHandler; NS_IMPL_ISUPPORTS1(GContentHandler, nsIHelperAppLauncherDialog) #ifdef MOZ_NSIMIMEINFO_NSACSTRING_ GContentHandler::GContentHandler() { LOG ("GContentHandler ctor (%p)", this) } #else GContentHandler::GContentHandler() : mMimeType(nsnull) { LOG ("GContentHandler ctor (%p)", this) } #endif GContentHandler::~GContentHandler() { LOG ("GContentHandler dtor (%p)", this) #ifndef MOZ_NSIMIMEINFO_NSACSTRING_ nsMemory::Free (mMimeType); #endif } //////////////////////////////////////////////////////////////////////////////// // begin nsIHelperAppLauncher impl //////////////////////////////////////////////////////////////////////////////// /* void show (in nsIHelperAppLauncher aLauncher, in nsISupports aContext); */ NS_IMETHODIMP GContentHandler::Show(nsIHelperAppLauncher *aLauncher, nsISupports *aContext, PRBool aForced) { nsresult rv; EphyEmbedSingle *single; gboolean handled = FALSE; mContext = aContext; mLauncher = aLauncher; rv = Init (); NS_ENSURE_SUCCESS (rv, rv); single = EPHY_EMBED_SINGLE (ephy_embed_shell_get_embed_single (embed_shell)); #ifdef MOZ_NSIMIMEINFO_NSACSTRING_ g_signal_emit_by_name (single, "handle_content", mMimeType.get(), mUrl.get(), &handled); #else g_signal_emit_by_name (single, "handle_content", mMimeType, mUrl.get(), &handled); #endif if (!handled) { MIMEDoAction (); } else { mLauncher->Cancel (); } 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; gint response; char *filename = NULL; nsEmbedCString defaultFile; NS_UTF16ToCString (nsEmbedString (aDefaultFile), NS_CSTRING_ENCODING_UTF8, defaultFile); if (mAction != CONTENT_ACTION_SAVEAS) { return BuildDownloadPath (defaultFile.get(), _retval); } nsCOMPtr parentDOMWindow = do_GetInterface (aWindowContext); GtkWidget *parentWindow = GTK_WIDGET (EphyUtils::FindGtkParent (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_current_name (GTK_FILE_CHOOSER (dialog), defaultFile.get()); 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_confirm_overwrite_file (GTK_WIDGET (dialog), filename)); if (response == GTK_RESPONSE_ACCEPT) { nsCOMPtr destFile (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID)); NS_ENSURE_TRUE (destFile, NS_ERROR_FAILURE); destFile->InitWithNativePath (nsEmbedCString (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::LaunchHelperApp (void) { nsCOMPtr helperService; helperService = do_GetService (NS_EXTERNALHELPERAPPSERVICE_CONTRACTID); NS_ENSURE_TRUE (helperService, NS_ERROR_FAILURE); nsCOMPtr appLauncher = do_QueryInterface (helperService); NS_ENSURE_TRUE (appLauncher, NS_ERROR_FAILURE); appLauncher->DeleteTemporaryFileOnExit(mTempFile); GList *params = NULL; char *param; param = gnome_vfs_make_uri_canonical (mUrl.get()); params = g_list_append (params, param); gnome_vfs_mime_application_launch (mHelperApp, params); g_free (param); g_list_free (params); mLauncher->Cancel(); return NS_OK; } NS_METHOD GContentHandler::CheckAppSupportScheme (void) { GList *l; mAppSupportScheme = PR_FALSE; if (!mHelperApp) return NS_OK; if (mHelperApp->expects_uris != GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS) return NS_OK; for (l = mHelperApp->supported_uri_schemes; l != NULL; l = l->next) { char *uri_scheme = (char *)l->data; if (strcmp (mScheme.get(), uri_scheme) == 0) { mAppSupportScheme = PR_TRUE; } } return NS_OK; } NS_METHOD GContentHandler::Init (void) { nsresult rv; NS_ENSURE_TRUE (mLauncher, NS_ERROR_FAILURE); nsCOMPtr MIMEInfo; mLauncher->GetMIMEInfo (getter_AddRefs(MIMEInfo)); NS_ENSURE_TRUE (MIMEInfo, NS_ERROR_FAILURE); #ifdef MOZ_NSIMIMEINFO_NSACSTRING_ rv = MIMEInfo->GetMIMEType (mMimeType); #else rv = MIMEInfo->GetMIMEType (&mMimeType); #endif mLauncher->GetTargetFile (getter_AddRefs(mTempFile)); mLauncher->GetSource (getter_AddRefs(mUri)); NS_ENSURE_TRUE (mUri, NS_ERROR_FAILURE); rv = mUri->GetSpec (mUrl); rv = mUri->GetScheme (mScheme); return NS_OK; } NS_METHOD GContentHandler::MIMEConfirmAction () { GtkWidget *dialog; const char *action_label, *primary, *secondary; int response; nsCOMPtr 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 : EPHY_STOCK_DOWNLOAD; if (mPermission == EPHY_MIME_PERMISSION_UNSAFE && mHelperApp) { primary = _("Download the unsafe file?"); secondary = _("This type of file could potentially damage " "your documents or invade your privacy. " "It's not safe to open it directly. " "You can save it instead."); } else if (mAction == CONTENT_ACTION_OPEN_TMP) { primary = _("Open the file in another application?"); secondary = _("It's not possible to view this file type " "directly in the browser. You can open it with " "another application or save it."); } else { primary = _("Download the file?"); secondary = _("It's not possible to view this file because " "there is no application installed that can open" " it. You can save it instead."); } dialog = gtk_message_dialog_new (parentWindow, GTK_DIALOG_MODAL /* FIXME mozilla sucks */, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, primary); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), secondary); gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Save As..."), CONTENT_ACTION_SAVEAS); gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, CONTENT_ACTION_NONE); gtk_dialog_add_button (GTK_DIALOG (dialog), action_label, mAction); gtk_window_set_icon_name (GTK_WINDOW (dialog), "web-browser"); gtk_dialog_set_default_response (GTK_DIALOG (dialog), (guint) mAction); response = gtk_dialog_run (GTK_DIALOG (dialog)); if (response == GTK_RESPONSE_DELETE_EVENT) { mAction = CONTENT_ACTION_NONE; } else { mAction = (ContentAction)response; } gtk_widget_destroy (dialog); return NS_OK; } NS_METHOD GContentHandler::MIMEDoAction (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); #ifdef MOZ_NSIMIMEINFO_NSACSTRING_ mHelperApp = gnome_vfs_mime_get_default_application (mMimeType.get()); mPermission = ephy_embed_shell_check_mime (embed_shell, mMimeType.get()); #else mHelperApp = gnome_vfs_mime_get_default_application (mMimeType); mPermission = ephy_embed_shell_check_mime (embed_shell, mMimeType); #endif CheckAppSupportScheme (); if (auto_downloads) { mAction = CONTENT_ACTION_OPEN; } else { mAction = CONTENT_ACTION_OPEN_TMP; } if (!mHelperApp || mPermission == EPHY_MIME_PERMISSION_UNSAFE) { mAction = CONTENT_ACTION_DOWNLOAD; } if (!auto_downloads || mAction == CONTENT_ACTION_DOWNLOAD) { MIMEConfirmAction (); } nsCOMPtr mimeInfo; mLauncher->GetMIMEInfo(getter_AddRefs(mimeInfo)); NS_ENSURE_TRUE (mimeInfo, NS_ERROR_FAILURE); if (mAction == CONTENT_ACTION_OPEN) { nsEmbedString desc; NS_CStringToUTF16 (nsEmbedCString ("gnome-default"), NS_CSTRING_ENCODING_UTF8, desc); /* HACK we use the application description to ask MozDownload to open the file when download is finished */ #ifdef MOZ_NSIMIMEINFO_NSACSTRING_ mimeInfo->SetApplicationDescription (desc); #else mimeInfo->SetApplicationDescription (desc.get()); #endif } else { #ifdef MOZ_NSIMIMEINFO_NSACSTRING_ mimeInfo->SetApplicationDescription (nsEmbedString ()); #else mimeInfo->SetApplicationDescription (nsnull); #endif } 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 (); } else { mLauncher->SaveToDisk (nsnull, PR_FALSE); } return NS_OK; }