Logo Search packages:      
Sourcecode: galeon version File versions

mozilla-embed-persist.cpp

/*
 *  Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "ProgressListener.h"
#include "mozilla-embed-persist.h"
#include "mozilla-embed.h"
#include "GaleonWrapper.h"
#include "gul-general.h"
#include "HeaderSniffer.h"
#include "galeon-debug.h"
#include "GaleonUtils.h"
#include "GulString.h"

#include <stddef.h>
#include <nsIServiceManager.h>
#include <nsIURIChecker.h>
#include <nsIHistoryEntry.h>
#include <nsISHEntry.h>
#include <nsISupportsPrimitives.h>
#include <nsIDOMDocument.h>
#include <nsIDOMNSDocument.h>
#include <nsIWebBrowser.h>
#include <nsIWebNavigation.h>
#include <nsISHistory.h>
#include <nsNetCID.h>
#include <nsILocalFile.h>
#include <nsIChannel.h>
#include <nsIIOService.h>
#include <nsIStreamListener.h>
#include <nsIURI.h>

struct MozillaEmbedPersistPrivate
{
      gpointer dummy;
};

#define MOZILLA_EMBED_PERSIST_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
                              MOZILLA_TYPE_EMBED_PERSIST, MozillaEmbedPersistPrivate))

G_DEFINE_TYPE (MozillaEmbedPersist, mozilla_embed_persist, GALEON_TYPE_EMBED_PERSIST);

static gboolean
impl_save (GaleonEmbedPersist *persist)
{
      nsresult rv;
      char *filename;
      char *uri;
      long max_size;
      GaleonEmbed *embed;
      EmbedPersistFlags flags;

      /* FIXME implement max size */

      g_object_get (persist,
                  "source", &uri,        
                  "dest", &filename,
                  "flags", &flags,
                  "embed", &embed,
                  "max_size", &max_size,
                  NULL);

      g_return_val_if_fail (uri || embed, FALSE);

      GaleonWrapper *wrapper = NULL;
      if (embed)
      {
            /* Don't bother holding the ref to the embed, its not about
             * to go away */
            g_object_unref (embed);

            wrapper = (GaleonWrapper *) mozilla_embed_get_galeon_wrapper (MOZILLA_EMBED(embed));
            NS_ENSURE_TRUE (wrapper, FALSE);
      }

      /* Get the uri to save from */
      nsCOMPtr<nsIURI> inURI;
      GulCString sURI;
      if (uri)
      {
            sURI.Assign (uri);
      }
      else if (flags & EMBED_PERSIST_MAINDOC)
      {
            rv = wrapper->GetMainDocumentUrl (sURI);
            NS_ENSURE_SUCCESS (rv, FALSE);
      }
      else
      {
            rv = wrapper->GetDocumentUrl (sURI);
            NS_ENSURE_SUCCESS (rv, FALSE);
      }
            GaleonUtils::NewURI(getter_AddRefs(inURI), sURI);
      if (!inURI) return FALSE;

      /* If the URI wasn't specified, we are using the embed, so
       * get the post data, DOM document and pageDescriptor */
      nsCOMPtr<nsIInputStream> postData;
      nsCOMPtr<nsIDOMDocument> DOMDocument;
      nsCOMPtr<nsISupports> pageDescriptor;
      if (!uri)
      {
            /* Post data */
            nsCOMPtr<nsISHistory> sessionHistory;
            nsCOMPtr<nsIHistoryEntry> entry;
            nsCOMPtr<nsIWebNavigation> webNav;
            PRInt32 sindex;

            webNav = do_QueryInterface(wrapper->mWebBrowser);
            webNav->GetSessionHistory(getter_AddRefs(sessionHistory));
            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 DOMDocument */
            if (flags & EMBED_PERSIST_MAINDOC)
            {
                  wrapper->GetMainDOMDocument (getter_AddRefs(DOMDocument));
            }
            else
            {
                  wrapper->GetDOMDocument (getter_AddRefs(DOMDocument));
            }
            NS_ENSURE_TRUE (DOMDocument, FALSE);

            /* and get the page descriptor */
              wrapper->GetPageDescriptor(getter_AddRefs(pageDescriptor));
            /* Its not the end of the world if we don't get
             * a pageDescriptor, mozilla doesn't even appear to use
             * it */
      }

      /* Only use the save document code if it an appropriate mime type,
       * we turn off the document save code, by just setting the
       * DOMDocument to null */
      if (DOMDocument)
      {
            nsCOMPtr<nsIDOMNSDocument> doc = do_QueryInterface(DOMDocument);
            GulString contentType;
            if (doc)
            {
                  doc->GetContentType (contentType);
            }

            if (!contentType.Equals (NS_LITERAL_STRING ("text/html")) &&
                !contentType.Equals (NS_LITERAL_STRING ("text/xml"))  &&
                !contentType.Equals (NS_LITERAL_STRING ("application/xhtml+xml")))
            {
                  DOMDocument = nsnull;
            }
      }

      if (filename == NULL)
      {
            /* Create an header sniffer and do the save */
            HeaderSniffer* sniffer = new HeaderSniffer (persist, inURI,
                                              DOMDocument, 
                                              postData,
                                              pageDescriptor);

            nsCOMPtr<nsIURIChecker> uri_checker = do_CreateInstance
                  (NS_URICHECKER_CONTRACT_ID);

            rv = uri_checker->Init (inURI);
            if (NS_FAILED (rv)) return FALSE;

            PRInt32 checker_flags = 0;
            if (flags & EMBED_PERSIST_BYPASSCACHE)
            {
                  checker_flags |= nsIRequest::LOAD_BYPASS_CACHE;
            }
            else
            {
                  checker_flags |= nsIRequest::LOAD_FROM_CACHE;
            }
            
            uri_checker->SetLoadFlags (checker_flags);

            /* Start the checker, the sniffer will inspect
             * the headers when it finishes */
            uri_checker->AsyncCheck (sniffer, nsnull);
      }
      else
      {
            /* Filename to save to */
            nsCOMPtr<nsILocalFile> destFile;
            NS_NewNativeLocalFile (GulDependentCString (filename),
                               PR_TRUE, getter_AddRefs(destFile));
              NS_ENSURE_TRUE (destFile, FALSE);

            rv =  InitiateMozillaDownload (inURI, destFile,
                                     persist, DOMDocument,
                                     pageDescriptor, postData,
                                     PR_TRUE, inURI);
            if (NS_FAILED (rv)) return FALSE;
      }

      g_free (uri);
      g_free (filename);

      return TRUE;
}

// ------------------------------------------------------------

class GStreamListener : public nsIStreamListener
{
public:
      NS_DECL_ISUPPORTS
      NS_DECL_NSIREQUESTOBSERVER
      NS_DECL_NSISTREAMLISTENER

      GStreamListener (GaleonEmbedPersist *aEmbedPersist,
                   GaleonEmbedPersistStreamFunc aFunc,
                   gpointer aData) : 
            mEmbedPersist (aEmbedPersist), mFunc (aFunc), mData (aData)
      {
            LOG("[%p] GStreamListener()", this);

            g_object_ref (mEmbedPersist);
      }

private:
      ~GStreamListener()
      {
            LOG("[%p] ~GStreamListener()", this);

            g_object_unref (mEmbedPersist);     
      }
      
      static NS_METHOD StreamReaderFunc (nsIInputStream* in, void* closure,
                                 const char* fromRawSegment,
                                 PRUint32 toOffset,  PRUint32 count,
                                 PRUint32 *writeCount);

      GaleonEmbedPersist *mEmbedPersist;
      GaleonEmbedPersistStreamFunc mFunc;
      gpointer mData;
};

NS_IMPL_ISUPPORTS1(GStreamListener, nsIStreamListener)

NS_METHOD
GStreamListener::StreamReaderFunc (nsIInputStream* in, void* closure,
                           const char* fromRawSegment,
                           PRUint32 toOffset,  PRUint32 count,
                           PRUint32 *writeCount)
{
      GStreamListener *listener = (GStreamListener *)closure;

      if (! listener->mFunc (listener->mEmbedPersist, fromRawSegment, count,
                         listener->mData))
      {
            /* Caller is not interested any more */
            listener->mFunc = NULL;

            *writeCount = 0;
            return NS_ERROR_FAILURE;
      }

      *writeCount = count;
      return NS_OK;
}

NS_IMETHODIMP
GStreamListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
                         nsIInputStream *aInputStream, 
                         PRUint32 aOffset, PRUint32 aCount)
{
      LOG("[%p] OnDataAvailable(%d, %d)", this, aOffset, aCount);

      PRUint32 totalRead;
      nsresult rv;
      rv = aInputStream->ReadSegments (GStreamListener::StreamReaderFunc,
                               (void*)this, aCount, &totalRead);
      NS_ENSURE_SUCCESS (rv, rv);

      return mFunc ? NS_OK : NS_ERROR_FAILURE;
}

/* void onStartRequest (in nsIRequest aRequest, in nsISupports aContext); */
NS_IMETHODIMP
GStreamListener::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
{
      LOG("[%p] OnStartRequest()", this);
      return NS_OK;
}

/* void onStopRequest (in nsIRequest aRequest, in nsISupports aContext, in nsresult aStatusCode); */
NS_IMETHODIMP
GStreamListener::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode)
{
      LOG("[%p] OnStopRequest()", this);

      if (aStatusCode == NS_OK && mFunc)
      {
            g_signal_emit_by_name (mEmbedPersist, "completed");
      }

      return NS_OK;
}


static gboolean
impl_stream (GaleonEmbedPersist *persist, GaleonEmbedPersistStreamFunc func,
           gpointer data)
{
      nsresult rv;
      char *source;
      GaleonEmbed *embed;
      EmbedPersistFlags flags;

      g_return_val_if_fail (GALEON_IS_EMBED_PERSIST (persist), FALSE);
      g_return_val_if_fail (func, FALSE);

      /* FIXME implement flags */

      g_object_get (persist,
                  "source", &source,
                  "flags", &flags,
                  "embed", &embed,
                  NULL);

      nsCOMPtr<nsIIOService> ioService;
      rv = GaleonUtils::GetIOService (getter_AddRefs (ioService));
      NS_ENSURE_SUCCESS (rv, rv);

      nsCOMPtr<nsIChannel> channel;
      rv = ioService->NewChannel (GulDependentCString (source), nsnull, nsnull, 
                            getter_AddRefs (channel));
      NS_ENSURE_SUCCESS (rv, rv);
      if (NS_FAILED (rv)) return FALSE;

      // referrer?
      nsCOMPtr<nsIStreamListener> listener = new GStreamListener (persist, func, data);
      rv = channel->AsyncOpen(listener, nsnull);
      if (NS_FAILED (rv)) return FALSE;

      return TRUE;
}

static void
mozilla_embed_persist_init (MozillaEmbedPersist *persist)
{
      persist->priv = MOZILLA_EMBED_PERSIST_GET_PRIVATE (persist);
}

static void
mozilla_embed_persist_finalize (GObject *object)
{
      G_OBJECT_CLASS (mozilla_embed_persist_parent_class)->finalize (object);
}

static void
mozilla_embed_persist_class_init (MozillaEmbedPersistClass *klass)
{
      GObjectClass *object_class;
      GaleonEmbedPersistClass *persist_class;
      
      persist_class = GALEON_EMBED_PERSIST_CLASS (klass);
      object_class  = G_OBJECT_CLASS (klass);

      object_class->finalize = mozilla_embed_persist_finalize;
      persist_class->save = impl_save;
      persist_class->stream = impl_stream;

      g_type_class_add_private (object_class, sizeof (MozillaEmbedPersistPrivate));
}

GaleonEmbedPersist *
galeon_embed_persist_new (GaleonEmbed *embed)
{
      GaleonEmbedPersist *persist;
      
      persist = GALEON_EMBED_PERSIST (g_object_new (MOZILLA_TYPE_EMBED_PERSIST,
                                          "embed", embed, NULL));

      return persist;
}

Generated by  Doxygen 1.6.0   Back to index