184 lines
5.6 KiB
C++
184 lines
5.6 KiB
C++
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <gtkmozembed.h>
|
|
#include <gtkmozembed_internal.h>
|
|
#include <nsIRequest.h>
|
|
#include <nsNetUtil.h>
|
|
#include <nsISeekableStream.h>
|
|
#include <nsIHttpChannel.h>
|
|
#include <nsIUploadChannel.h>
|
|
#include <nsIWebBrowser.h>
|
|
#include <nsISHistory.h>
|
|
#include <nsIHistoryEntry.h>
|
|
#include <nsISHEntry.h>
|
|
#include <nsIInputStream.h>
|
|
#include <nsIWebNavigation.h>
|
|
|
|
#include "GeckoBrowserPersist.h"
|
|
|
|
GeckoBrowserPersist::GeckoBrowserPersist(SugarBrowser *browser)
|
|
: mBrowser(browser)
|
|
{
|
|
}
|
|
|
|
GeckoBrowserPersist::~GeckoBrowserPersist()
|
|
{
|
|
}
|
|
|
|
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
|
|
GetPostData(SugarBrowser *browser, nsIInputStream **postData)
|
|
{
|
|
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;
|
|
}
|
|
|
|
bool
|
|
GeckoBrowserPersist::SaveURI(const char *uri, const char *filename)
|
|
{
|
|
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<nsIInputStream> postData;
|
|
GetPostData(mBrowser, getter_AddRefs(postData));
|
|
|
|
nsCOMPtr<nsIChannel> inputChannel;
|
|
rv = NS_NewChannel(getter_AddRefs(inputChannel), sourceURI,
|
|
nsnull, nsnull, nsnull, nsIRequest::LOAD_NORMAL);
|
|
NS_ENSURE_SUCCESS(rv, FALSE);
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(inputChannel));
|
|
if (httpChannel) {
|
|
nsCOMPtr<nsISeekableStream> stream(do_QueryInterface(postData));
|
|
if (stream)
|
|
{
|
|
// Rewind the postdata stream
|
|
stream->Seek(nsISeekableStream::NS_SEEK_SET, 0);
|
|
nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
|
|
NS_ASSERTION(uploadChannel, "http must support nsIUploadChannel");
|
|
// Attach the postdata to the http channel
|
|
uploadChannel->SetUploadStream(postData, EmptyCString(), -1);
|
|
}
|
|
}
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
|
rv = inputChannel->Open(getter_AddRefs(stream));
|
|
NS_ENSURE_SUCCESS(rv, FALSE);
|
|
|
|
nsCOMPtr<nsIFileOutputStream> fileOutputStream =
|
|
do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, FALSE);
|
|
|
|
rv = fileOutputStream->Init(destFile, -1, -1, 0);
|
|
NS_ENSURE_SUCCESS(rv, FALSE);
|
|
|
|
// Read data from the input and write to the output
|
|
char buffer[8192];
|
|
PRUint32 bytesRead;
|
|
PRUint32 bytesRemaining;
|
|
PRBool cancel = PR_FALSE;
|
|
PRBool readError;
|
|
|
|
rv = stream->Available(&bytesRemaining);
|
|
NS_ENSURE_SUCCESS(rv, FALSE);
|
|
|
|
while (!cancel && bytesRemaining)
|
|
{
|
|
readError = PR_TRUE;
|
|
rv = stream->Read(buffer, PR_MIN(sizeof(buffer), bytesRemaining), &bytesRead);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
readError = PR_FALSE;
|
|
// Write out the data until something goes wrong, or, it is
|
|
// all written. We loop because for some errors (e.g., disk
|
|
// full), we get NS_OK with some bytes written, then an error.
|
|
// So, we want to write again in that case to get the actual
|
|
// error code.
|
|
const char *bufPtr = buffer; // Where to write from.
|
|
while (NS_SUCCEEDED(rv) && bytesRead)
|
|
{
|
|
PRUint32 bytesWritten = 0;
|
|
rv = fileOutputStream->Write(bufPtr, bytesRead, &bytesWritten);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
bytesRead -= bytesWritten;
|
|
bufPtr += bytesWritten;
|
|
bytesRemaining -= bytesWritten;
|
|
// Force an error if (for some reason) we get NS_OK but
|
|
// no bytes written.
|
|
if (!bytesWritten)
|
|
{
|
|
rv = NS_ERROR_FAILURE;
|
|
cancel = PR_TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Disaster - can't write out the bytes - disk full / permission?
|
|
cancel = PR_TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Disaster - can't read the bytes - broken link / file error?
|
|
cancel = PR_TRUE;
|
|
}
|
|
}
|
|
NS_ENSURE_SUCCESS(rv, FALSE);
|
|
|
|
stream->Close();
|
|
|
|
return TRUE;
|
|
}
|