/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 mPersist; }; G_DEFINE_TYPE (MozillaEmbedPersist, mozilla_embed_persist, EPHY_TYPE_EMBED_PERSIST) 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 (mozilla_embed_persist_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 bpersist = MOZILLA_EMBED_PERSIST (persist)->priv->mPersist; nsCOMPtr 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 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 postData; /* FIXME: don't do this on COPY_PAGE to ensure we don't end up reposting? */ if (browser) { PRInt32 sindex; nsCOMPtr webNav(do_QueryInterface(browser->mWebBrowser)); nsCOMPtr sessionHistory; webNav->GetSessionHistory(getter_AddRefs(sessionHistory)); nsCOMPtr entry; sessionHistory->GetIndex(&sindex); sessionHistory->GetEntryAtIndex(sindex, PR_FALSE, getter_AddRefs(entry)); nsCOMPtr shEntry(do_QueryInterface(entry)); if (shEntry) { shEntry->GetPostData(getter_AddRefs(postData)); } } /* Get the DOM document if a uri is not specified */ nsCOMPtr 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 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 cacheService (do_GetService(NS_CACHESERVICE_CONTRACTID)); if (cacheService) { nsCOMPtr cacheSession; rv = cacheService->CreateSession ("HTTP", nsICache::STORE_ANYWHERE, PR_TRUE, getter_AddRefs (cacheSession)); if (NS_SUCCEEDED (rv) && cacheSession) { nsCOMPtr 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 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 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 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 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 node = do_QueryInterface(DOMDocument); if (node) { nsString outString; nsCOMPtr 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 G_OBJECT_CLASS (mozilla_embed_persist_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); 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)); }