From 2a93fb20b6618d44c05589bb636fe77b7b04e075 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Fri, 24 Oct 2003 10:56:53 +0000 Subject: Add an helper to initialize downloads. 2003-10-24 Marco Pesenti Gritti * embed/mozilla/MozDownload.cpp: * embed/mozilla/MozDownload.h: Add an helper to initialize downloads. * embed/ephy-embed-persist.h: Add a flag to ask destination. * embed/mozilla/EphyHeaderSniffer.cpp: * embed/mozilla/EphyHeaderSniffer.h: Use the helper. Add code to determine a good filename. * embed/mozilla/mozilla-embed-persist.cpp: Use a MozDownload directly if there is a dest set, it doesnt make sense to use sniffer for favicons. --- ChangeLog | 22 +++++ embed/ephy-embed-persist.h | 3 +- embed/mozilla/EphyHeaderSniffer.cpp | 167 +++++++++++++------------------- embed/mozilla/EphyHeaderSniffer.h | 5 +- embed/mozilla/MozDownload.cpp | 96 ++++++++++++++++++ embed/mozilla/MozDownload.h | 7 ++ embed/mozilla/mozilla-embed-persist.cpp | 48 +++++---- 7 files changed, 229 insertions(+), 119 deletions(-) diff --git a/ChangeLog b/ChangeLog index 98a5ddad1..54ebdc209 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2003-10-24 Marco Pesenti Gritti + + * embed/mozilla/MozDownload.cpp: + * embed/mozilla/MozDownload.h: + + Add an helper to initialize downloads. + + * embed/ephy-embed-persist.h: + + Add a flag to ask destination. + + * embed/mozilla/EphyHeaderSniffer.cpp: + * embed/mozilla/EphyHeaderSniffer.h: + + Use the helper. Add code to determine a good + filename. + + * embed/mozilla/mozilla-embed-persist.cpp: + + Use a MozDownload directly if there is a dest set, + it doesnt make sense to use sniffer for favicons. + 2003-10-23 Marco Pesenti Gritti * lib/egg/egg-editable-toolbar.c: (create_item_from_action), diff --git a/embed/ephy-embed-persist.h b/embed/ephy-embed-persist.h index ad0a702b2..1a48d2455 100644 --- a/embed/ephy-embed-persist.h +++ b/embed/ephy-embed-persist.h @@ -41,7 +41,8 @@ typedef enum { EMBED_PERSIST_BYPASSCACHE = 1 << 0, EMBED_PERSIST_MAINDOC = 1 << 1, - EMBED_PERSIST_NO_VIEW = 1 << 2 + EMBED_PERSIST_NO_VIEW = 1 << 2, + EMBED_PERSIST_ASK_DESTINATION = 1 << 3 } EmbedPersistFlags; typedef struct diff --git a/embed/mozilla/EphyHeaderSniffer.cpp b/embed/mozilla/EphyHeaderSniffer.cpp index efeb90e4a..8fbf2220b 100644 --- a/embed/mozilla/EphyHeaderSniffer.cpp +++ b/embed/mozilla/EphyHeaderSniffer.cpp @@ -36,6 +36,8 @@ * * ***** END LICENSE BLOCK ***** */ +#include "MozillaPrivate.h" + #include "MozDownload.h" #include "EphyHeaderSniffer.h" #include "netCore.h" @@ -51,19 +53,15 @@ #include "nsIDOMHTMLDocument.h" #include "nsIDownload.h" -const char* const persistContractID = "@mozilla.org/embedding/browser/nsWebBrowserPersist;1"; - EphyHeaderSniffer::EphyHeaderSniffer (nsIWebBrowserPersist* aPersist, MozillaEmbedPersist *aEmbedPersist, nsIFile* aFile, nsIURI* aURL, nsIDOMDocument* aDocument, nsIInputStream* aPostData, - const nsAString& aSuggestedFilename, PRBool aBypassCache) + PRBool aBypassCache) : mPersist(aPersist) , mEmbedPersist(aEmbedPersist) , mTmpFile(aFile) , mURL(aURL) , mDocument(aDocument) , mPostData(aPostData) -, mDefaultFilename(aSuggestedFilename) -, mBypassCache(aBypassCache) { mPrompt = do_GetService("@mozilla.org/embedcomp/prompt-service;1"); } @@ -157,116 +155,91 @@ EphyHeaderSniffer::OnSecurityChange (nsIWebProgress *aWebProgress, nsIRequest *a nsresult EphyHeaderSniffer::PerformSave (nsIURI* inOriginalURI) { nsresult rv; + EmbedPersistFlags flags; + PRBool askDownloadDest; - PRBool isHTML = (mDocument && mContentType.Equals("text/html") || - mContentType.Equals("text/xml") || - mContentType.Equals("application/xhtml+xml")); + ephy_embed_persist_get_flags (EPHY_EMBED_PERSIST (mEmbedPersist), &flags); + askDownloadDest = flags & EMBED_PERSIST_ASK_DESTINATION; - nsCOMPtr file; - rv = NS_NewLocalFile(mDefaultFilename, PR_TRUE, getter_AddRefs(file)); - if (NS_FAILED(rv) || !file) return G_FAILED; - - nsCOMPtr sourceData; - if (isHTML) + nsAutoString defaultFileName; + + if (defaultFileName.IsEmpty() && !mContentDisposition.IsEmpty()) { - sourceData = do_QueryInterface(mDocument); + /* 1 Use the HTTP header suggestion. */ + PRInt32 index = mContentDisposition.Find("filename="); + if (index >= 0) + { + /* Take the substring following the prefix. */ + index += 9; + nsCAutoString filename; + mContentDisposition.Right(filename, mContentDisposition.Length() - index); + defaultFileName = NS_ConvertUTF8toUCS2(filename); + } } - else + + if (defaultFileName.IsEmpty()) { - sourceData = do_QueryInterface(mURL); - } - - return InitiateDownload(sourceData, file, inOriginalURI); -} + /* 2 For file URLs, use the file name. */ -nsresult EphyHeaderSniffer::InitiateDownload (nsISupports* inSourceData, nsILocalFile* inDestFile, - nsIURI* inOriginalURI) -{ - nsresult rv = NS_OK; - - nsCOMPtr webPersist = do_CreateInstance(persistContractID, &rv); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr sourceURI = do_QueryInterface(inSourceData); - - PRInt64 timeNow = PR_Now(); - - nsAutoString fileDisplayName; - inDestFile->GetLeafName(fileDisplayName); - - MozDownload *downloader = new MozDownload (); - /* dlListener attaches to its progress dialog here, which gains ownership */ - rv = downloader->InitForEmbed (inOriginalURI, inDestFile, fileDisplayName.get(), - nsnull, timeNow, webPersist, mEmbedPersist); - if (NS_FAILED(rv)) return rv; - - PRInt32 flags = nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION | - nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES; - if (mBypassCache) + nsCOMPtr url(do_QueryInterface(mURL)); + if (url) + { + nsCAutoString fileNameCString; + url->GetFileName(fileNameCString); + defaultFileName = NS_ConvertUTF8toUCS2(fileNameCString); + } + } + + if (defaultFileName.IsEmpty() && mDocument) { - flags |= nsIWebBrowserPersist::PERSIST_FLAGS_BYPASS_CACHE; + /* 3 Use the title of the document. */ + + nsCOMPtr htmlDoc(do_QueryInterface(mDocument)); + if (htmlDoc) + { + htmlDoc->GetTitle(defaultFileName); + } } - else + + if (defaultFileName.IsEmpty() && mURL) { - flags |= nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE; + /* 4 Use the host. */ + nsCAutoString hostName; + mURL->GetHost(hostName); + defaultFileName = NS_ConvertUTF8toUCS2(hostName); } - - webPersist->SetPersistFlags(flags); - if (sourceURI) + /* 5 One last case to handle about:blank and other fruity untitled pages. */ + if (defaultFileName.IsEmpty()) { - rv = webPersist->SaveURI (sourceURI, nsnull, nsnull, - mPostData, nsnull, inDestFile); + defaultFileName.AssignWithConversion("untitled"); } - else + + /* Validate the file name to ensure legality. */ + for (PRUint32 i = 0; i < defaultFileName.Length(); i++) { - nsCOMPtr domDoc = do_QueryInterface(inSourceData, &rv); - if (!domDoc) return rv; /* should never happen */ - - PRInt32 encodingFlags = 0; - nsCOMPtr filesFolder; - - if (!mContentType.Equals("text/plain")) + if (defaultFileName[i] == ':' || defaultFileName[i] == '/') { - /* Create a local directory in the same dir as our file. It - will hold our associated files. */ - - filesFolder = do_CreateInstance("@mozilla.org/file/local;1"); - nsAutoString unicodePath; - inDestFile->GetPath(unicodePath); - filesFolder->InitWithPath(unicodePath); - - nsAutoString leafName; - filesFolder->GetLeafName(leafName); - nsAutoString nameMinusExt(leafName); - PRInt32 index = nameMinusExt.RFind("."); - if (index >= 0) - { - nameMinusExt.Left(nameMinusExt, index); - } - - nameMinusExt += NS_LITERAL_STRING(" Files"); - filesFolder->SetLeafName(nameMinusExt); - PRBool exists = PR_FALSE; - filesFolder->Exists(&exists); - if (!exists) - { - rv = filesFolder->Create(nsILocalFile::DIRECTORY_TYPE, 0755); - if (NS_FAILED(rv)) return rv; - } - } - else - { - encodingFlags |= nsIWebBrowserPersist::ENCODE_FLAGS_FORMATTED | - nsIWebBrowserPersist::ENCODE_FLAGS_ABSOLUTE_LINKS | - nsIWebBrowserPersist::ENCODE_FLAGS_NOFRAMES_CONTENT; + defaultFileName.SetCharAt(i, PRUnichar(' ')); } + } - rv = webPersist->SaveDocument (domDoc, inDestFile, filesFolder, - mContentType.get(), encodingFlags, 80); + if (askDownloadDest) + { + /* FIXME show the file selector here */ + } + else + { + /* FIXME build path from download dir */ } - - return rv; + + nsCOMPtr destFile; + rv = NS_NewLocalFile(defaultFileName, PR_TRUE, getter_AddRefs(destFile)); + if (NS_FAILED(rv) || !destFile) return G_FAILED; + + return InitiateMozillaDownload (mDocument, mURL, destFile, + mContentType.get(), inOriginalURI, mEmbedPersist, + mBypassCache, mPostData); } NS_IMETHODIMP EphyHeaderSniffer::Prompt (const PRUnichar *dialogTitle, const PRUnichar *text, diff --git a/embed/mozilla/EphyHeaderSniffer.h b/embed/mozilla/EphyHeaderSniffer.h index b8d56281d..3635593e8 100644 --- a/embed/mozilla/EphyHeaderSniffer.h +++ b/embed/mozilla/EphyHeaderSniffer.h @@ -54,8 +54,7 @@ class EphyHeaderSniffer : public nsIWebProgressListener, public: EphyHeaderSniffer (nsIWebBrowserPersist* aPersist, MozillaEmbedPersist *aEmbedPersist, nsIFile* aFile, nsIURI* aURL, - nsIDOMDocument* aDocument, nsIInputStream* aPostData, - const nsAString& aSuggestedFilename, PRBool aBypassCache); + nsIDOMDocument* aDocument, nsIInputStream* aPostData, PRBool aBypassCache); virtual ~EphyHeaderSniffer (); NS_DECL_ISUPPORTS @@ -64,7 +63,6 @@ public: protected: nsresult PerformSave (nsIURI* inOriginalURI); - nsresult InitiateDownload (nsISupports* inSourceData, nsILocalFile* inDestFile, nsIURI* inOriginalURI); private: nsIWebBrowserPersist* mPersist; /* Weak. It owns us as a listener. */ @@ -73,7 +71,6 @@ private: nsCOMPtr mURL; nsCOMPtr mDocument; nsCOMPtr mPostData; - nsString mDefaultFilename; PRBool mBypassCache; nsCString mContentType; nsCString mContentDisposition; diff --git a/embed/mozilla/MozDownload.cpp b/embed/mozilla/MozDownload.cpp index 2c7be9a07..e6ee3d0eb 100644 --- a/embed/mozilla/MozDownload.cpp +++ b/embed/mozilla/MozDownload.cpp @@ -48,6 +48,8 @@ #include "netCore.h" #include "nsIObserver.h" +const char* const persistContractID = "@mozilla.org/embedding/browser/nsWebBrowserPersist;1"; + MozDownload::MozDownload() : mGotFirstStateChange(false), mIsNetworkTransfer(false), mUserCanceled(false), @@ -376,3 +378,97 @@ void MozDownload::Resume() { } + +nsresult InitiateMozillaDownload (nsIDOMDocument *domDocument, nsIURI *sourceURI, + nsILocalFile* inDestFile, const char *contentType, + nsIURI* inOriginalURI, MozillaEmbedPersist *embedPersist, + PRBool bypassCache, nsIInputStream *postData) +{ + nsresult rv = NS_OK; + + PRBool isHTML = (domDocument && contentType && + (strcmp (contentType, "text/html") == 0 || + strcmp (contentType, "text/xml") == 0 || + strcmp (contentType, "application/xhtml+xml") == 0)); + + nsCOMPtr webPersist = do_CreateInstance(persistContractID, &rv); + if (NS_FAILED(rv)) return rv; + + PRInt64 timeNow = PR_Now(); + + nsAutoString fileDisplayName; + inDestFile->GetLeafName(fileDisplayName); + + MozDownload *downloader = new MozDownload (); + /* dlListener attaches to its progress dialog here, which gains ownership */ + rv = downloader->InitForEmbed (inOriginalURI, inDestFile, fileDisplayName.get(), + nsnull, timeNow, webPersist, embedPersist); + if (NS_FAILED(rv)) return rv; + + PRInt32 flags = nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION | + nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES; + if (bypassCache) + { + flags |= nsIWebBrowserPersist::PERSIST_FLAGS_BYPASS_CACHE; + } + else + { + flags |= nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE; + } + + webPersist->SetPersistFlags(flags); + + if (!isHTML) + { + rv = webPersist->SaveURI (sourceURI, nsnull, nsnull, + postData, nsnull, inDestFile); + } + else + { + if (!domDocument) return rv; /* should never happen */ + + PRInt32 encodingFlags = 0; + nsCOMPtr filesFolder; + + if (contentType && strcmp (contentType, "text/plain") == 0) + { + /* Create a local directory in the same dir as our file. It + will hold our associated files. */ + + filesFolder = do_CreateInstance("@mozilla.org/file/local;1"); + nsAutoString unicodePath; + inDestFile->GetPath(unicodePath); + filesFolder->InitWithPath(unicodePath); + + nsAutoString leafName; + filesFolder->GetLeafName(leafName); + nsAutoString nameMinusExt(leafName); + PRInt32 index = nameMinusExt.RFind("."); + if (index >= 0) + { + nameMinusExt.Left(nameMinusExt, index); + } + + nameMinusExt += NS_LITERAL_STRING(" Files"); + filesFolder->SetLeafName(nameMinusExt); + PRBool exists = PR_FALSE; + filesFolder->Exists(&exists); + if (!exists) + { + rv = filesFolder->Create(nsILocalFile::DIRECTORY_TYPE, 0755); + if (NS_FAILED(rv)) return rv; + } + } + else + { + encodingFlags |= nsIWebBrowserPersist::ENCODE_FLAGS_FORMATTED | + nsIWebBrowserPersist::ENCODE_FLAGS_ABSOLUTE_LINKS | + nsIWebBrowserPersist::ENCODE_FLAGS_NOFRAMES_CONTENT; + } + + rv = webPersist->SaveDocument (domDocument, inDestFile, filesFolder, + contentType, encodingFlags, 80); + } + + return rv; +} diff --git a/embed/mozilla/MozDownload.h b/embed/mozilla/MozDownload.h index 56b8e16e1..49f0e6cc9 100644 --- a/embed/mozilla/MozDownload.h +++ b/embed/mozilla/MozDownload.h @@ -44,7 +44,9 @@ #include "nsIWebProgressListener.h" #include "nsIHelperAppLauncherDialog.h" #include "nsIExternalHelperAppService.h" +#include "nsIDOMDocument.h" +#include "nsString.h" #include "nsIURI.h" #include "nsILocalFile.h" #include "nsIWebBrowserPersist.h" @@ -74,6 +76,11 @@ #define MOZ_DOWNLOAD_CLASSNAME "Ephy's Download Progress Dialog" +nsresult InitiateMozillaDownload (nsIDOMDocument *domDocument, nsIURI *sourceUri, + nsILocalFile* inDestFile, const char *contentType, + nsIURI* inOriginalURI, MozillaEmbedPersist *embedPersist, + PRBool bypassCache, nsIInputStream *postData); + class MozDownload : public nsIDownload, public nsIWebProgressListener { diff --git a/embed/mozilla/mozilla-embed-persist.cpp b/embed/mozilla/mozilla-embed-persist.cpp index 846b63c8d..8ba3596e8 100644 --- a/embed/mozilla/mozilla-embed-persist.cpp +++ b/embed/mozilla/mozilla-embed-persist.cpp @@ -20,6 +20,7 @@ #include "EphyWrapper.h" #include "EphyHeaderSniffer.h" +#include "MozDownload.h" #include "mozilla-embed.h" #include "mozilla-embed-persist.h" @@ -206,10 +207,6 @@ impl_save (EphyEmbedPersist *persist) rv = NS_NewURI(getter_AddRefs(inURI), sURI); if (NS_FAILED(rv) || !inURI) return G_FAILED; - /* Filename to save to */ - nsAutoString inFilename; - inFilename.AssignWithConversion (filename); - /* Get post data */ nsCOMPtr postData; if (wrapper) @@ -244,20 +241,37 @@ impl_save (EphyEmbedPersist *persist) if (NS_FAILED(rv) || !DOMDocument) return G_FAILED; } - /* Create an header sniffer and do the save */ - nsCOMPtr webPersist = - MOZILLA_EMBED_PERSIST (persist)->priv->mPersist; - if (!webPersist) return G_FAILED; - - EphyHeaderSniffer* sniffer = new EphyHeaderSniffer - (webPersist, MOZILLA_EMBED_PERSIST (persist), - tmpFile, inURI, DOMDocument, postData, - inFilename, flags & EMBED_PERSIST_BYPASSCACHE); - if (!sniffer) return G_FAILED; + if (filename == NULL) + { + /* Create an header sniffer and do the save */ + nsCOMPtr webPersist = + MOZILLA_EMBED_PERSIST (persist)->priv->mPersist; + if (!webPersist) return G_FAILED; + + EphyHeaderSniffer* sniffer = new EphyHeaderSniffer + (webPersist, MOZILLA_EMBED_PERSIST (persist), + tmpFile, inURI, DOMDocument, postData, + flags & EMBED_PERSIST_BYPASSCACHE); + if (!sniffer) return G_FAILED; - webPersist->SetProgressListener(sniffer); - rv = webPersist->SaveURI(inURI, nsnull, nsnull, nsnull, nsnull, tmpFile); - if (NS_FAILED (rv)) return G_FAILED; + webPersist->SetProgressListener(sniffer); + rv = webPersist->SaveURI(inURI, nsnull, nsnull, nsnull, nsnull, tmpFile); + if (NS_FAILED (rv)) return G_FAILED; + } + else + { + /* Filename to save to */ + nsCOMPtr destFile; + rv = NS_NewNativeLocalFile (nsDependentCString(filename), + PR_TRUE, getter_AddRefs(destFile)); + if (NS_FAILED(rv) || !destFile) return G_FAILED; + + rv = InitiateMozillaDownload (DOMDocument, inURI, destFile, + nsnull, inURI, MOZILLA_EMBED_PERSIST (persist), + flags & EMBED_PERSIST_BYPASSCACHE, + postData); + if (NS_FAILED (rv)) return G_FAILED; + } return G_OK; } -- cgit v1.2.3