diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index a8c14b4a8963..16670c3fb0dd 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -5455,6 +5455,7 @@ nsDocShell::AddHeadersToChannel(nsIInputStream * aHeadersData, // add the value as a header to the nsIHttpChannel // + const char *kWhitespace = "\b\t\r\n "; while (PR_TRUE) { crlf = headersString.Find("\r\n", PR_TRUE); if (-1 == crlf) { @@ -5462,7 +5463,6 @@ nsDocShell::AddHeadersToChannel(nsIInputStream * aHeadersData, } headersString.Mid(oneHeader, 0, crlf); headersString.Cut(0, crlf + 2); - oneHeader.StripWhitespace(); colon = oneHeader.Find(":"); if (-1 == colon) { return NS_ERROR_NULL_POINTER; @@ -5470,6 +5470,8 @@ nsDocShell::AddHeadersToChannel(nsIInputStream * aHeadersData, oneHeader.Left(headerName, colon); colon++; oneHeader.Mid(headerValue, colon, oneHeader.Length() - colon); + headerName.Trim(kWhitespace); + headerValue.Trim(kWhitespace); // // FINALLY: we can set the header! diff --git a/embedding/browser/photon/src/EmbedWindow.cpp b/embedding/browser/photon/src/EmbedWindow.cpp index 568f5072d1e8..9f4772a07ff1 100644 --- a/embedding/browser/photon/src/EmbedWindow.cpp +++ b/embedding/browser/photon/src/EmbedWindow.cpp @@ -204,7 +204,7 @@ EmbedWindow::SaveURI(nsIURI *uri, char *fname) nsCOMPtr file; NS_NewNativeLocalFile(nsDependentCString(fname), PR_TRUE, getter_AddRefs(file)); persist->SetProgressListener((nsIWebProgressListener*) w->EmbedRef->mProgress); - persist->SaveURI(uri, nsnull, file); + persist->SaveURI(uri, nsnull, nsnull, nsnull, nsnull, file); return (0); } return 1; diff --git a/embedding/browser/powerplant/source/CBrowserShell.cpp b/embedding/browser/powerplant/source/CBrowserShell.cpp index df043d990b93..a4d4299d07c7 100644 --- a/embedding/browser/powerplant/source/CBrowserShell.cpp +++ b/embedding/browser/powerplant/source/CBrowserShell.cpp @@ -1220,7 +1220,7 @@ NS_METHOD CBrowserShell::SaveInternal(nsIURI* inURI, nsIDOMDocument* inDocument, webPersist->SetProgressListener(sniffer); // owned - return webPersist->SaveURI(inURI, nsnull, tmpFile); + return webPersist->SaveURI(inURI, nsnull, nsnull, nsnull, nsnull, tmpFile); } diff --git a/embedding/browser/powerplant/source/CHeaderSniffer.cpp b/embedding/browser/powerplant/source/CHeaderSniffer.cpp index a16cca4d680b..773e0f2aa654 100644 --- a/embedding/browser/powerplant/source/CHeaderSniffer.cpp +++ b/embedding/browser/powerplant/source/CHeaderSniffer.cpp @@ -404,7 +404,7 @@ nsresult CHeaderSniffer::InitiateDownload(nsISupports* inSourceData, nsILocalFil if (sourceURI) { - rv = webPersist->SaveURI(sourceURI, mPostData, inDestFile); + rv = webPersist->SaveURI(sourceURI, nsnull, nsnull, mPostData, nsnull, inDestFile); } else { diff --git a/embedding/browser/webBrowser/nsWebBrowser.cpp b/embedding/browser/webBrowser/nsWebBrowser.cpp index f78df0ae9ee3..b6a11b8b9ab8 100644 --- a/embedding/browser/webBrowser/nsWebBrowser.cpp +++ b/embedding/browser/webBrowser/nsWebBrowser.cpp @@ -890,8 +890,12 @@ NS_IMETHODIMP nsWebBrowser::SetProgressListener(nsIWebProgressListener * aProgre return NS_OK; } -/* void saveURI (in nsIURI aURI, in nsISupports aFile); */ -NS_IMETHODIMP nsWebBrowser::SaveURI(nsIURI *aURI, nsIInputStream *aPostData, nsISupports *aFile) +/* void saveURI (in nsIURI aURI, in nsIURI aReferrer, + in nsISupports aCacheKey, in nsIInputStream aPostData, in wstring aExtraHeaders, + in nsISupports aFile); */ +NS_IMETHODIMP nsWebBrowser::SaveURI( + nsIURI *aURI, nsISupports *aCacheKey, nsIURI *aReferrer, nsIInputStream *aPostData, + const char *aExtraHeaders, nsISupports *aFile) { if (mPersist) { @@ -929,7 +933,7 @@ NS_IMETHODIMP nsWebBrowser::SaveURI(nsIURI *aURI, nsIInputStream *aPostData, nsI mPersist->SetProgressListener(this); mPersist->SetPersistFlags(mPersistFlags); mPersist->GetCurrentState(&mPersistCurrentState); - rv = mPersist->SaveURI(uri, aPostData, aFile); + rv = mPersist->SaveURI(uri, aCacheKey, aReferrer, aPostData, aExtraHeaders, aFile); if (NS_FAILED(rv)) { mPersist = nsnull; diff --git a/embedding/components/ui/progressDlg/nsProgressDlg.js b/embedding/components/ui/progressDlg/nsProgressDlg.js index 1468378e3aec..f0f108bad200 100644 --- a/embedding/components/ui/progressDlg/nsProgressDlg.js +++ b/embedding/components/ui/progressDlg/nsProgressDlg.js @@ -394,7 +394,7 @@ function onLoad() { try { var uri = persistArgs.source.QueryInterface(Components.interfaces.nsIURI); - webBrowserPersist.saveURI(uri, persistArgs.postData, targetFile); + webBrowserPersist.saveURI(uri, null, null, persistArgs.postData, null, targetFile); } catch (e) { // Saving a Document, not a URI: diff --git a/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl b/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl index 71757dd6b956..f3834f4ace0d 100644 --- a/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl +++ b/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl @@ -33,7 +33,7 @@ interface nsILocalFile; */ /** - * Interface for persisting DOM documents and URIs to local storage. + * Interface for persisting DOM documents and URIs to local or remote storage. */ [scriptable, uuid(814ba433-a816-4785-9f95-ad3ba0a43dab)] interface nsIWebBrowserPersist : nsISupports @@ -63,7 +63,11 @@ interface nsIWebBrowserPersist : nsISupports /** Force serialization of output (one file at a time; not concurrent) */ const unsigned long PERSIST_FLAGS_SERIALIZE_OUTPUT = 1024; - /** Flags governing how data is fetched from the network. */ + /** + * Flags governing how data is fetched and saved from the network. + * It is best to set this value explicitly unless you are prepared + * to accept the default values. + */ attribute unsigned long persistFlags; /** Persister is ready to save data */ @@ -105,17 +109,28 @@ interface nsIWebBrowserPersist : nsISupports * @param aURI URI to save to file. Some implementations of this interface * may also support nsnull to imply the currently * loaded URI. - * @param aPostData Data to pass with in an HTTP request or nsnull. - * @param aFile Target local file. This may be a nsILocalFile object or an - * nsIURI object with a file scheme. + * @param aCacheKey An object representing the URI in the cache or + * nsnull. + * @param aReferrer The referrer URI to pass with an HTTP request or + * nsnull. + * @param aPostData Post data to pass with an HTTP request or + * nsnull. + * @param aExtraHeaders Additional headers to supply with an HTTP request + * or nsnull. + * @param aFile Target file. This may be a nsILocalFile object or an + * nsIURI object with a file scheme or a scheme that + * supports uploading (e.g. ftp). * * @see nsILocalFile * @see nsIURI + * @see nsIInputStream * * @return NS_OK Operation has been started. * @return NS_ERROR_INVALID_ARG One or more arguments was invalid. */ - void saveURI(in nsIURI aURI, in nsIInputStream aPostData, in nsISupports aFile); + void saveURI(in nsIURI aURI, in nsISupports aCacheKey, + in nsIURI aReferrer, in nsIInputStream aPostData, + in string aExtraHeaders, in nsISupports aFile); /** Output only the current selection as opposed to the whole document. */ const unsigned long ENCODE_FLAGS_SELECTION_ONLY = 1; @@ -197,7 +212,8 @@ interface nsIWebBrowserPersist : nsISupports * this interface may also support nsnull * to imply the currently loaded document. * @param aFile Target local file. This may be a nsILocalFile object or an - * nsIURI object with a file scheme. + * nsIURI object with a file scheme or a scheme that + * supports uploading (e.g. ftp). * @param aDataPath Path to directory where URIs linked to the document * are saved or nsnull if no linked URIs should be saved. * This may be a nsILocalFile object or an nsIURI object diff --git a/embedding/components/webbrowserpersist/src/Makefile.in b/embedding/components/webbrowserpersist/src/Makefile.in index 510e8c9248b0..c7aec1b5baba 100644 --- a/embedding/components/webbrowserpersist/src/Makefile.in +++ b/embedding/components/webbrowserpersist/src/Makefile.in @@ -38,6 +38,8 @@ REQUIRES = xpcom \ mimetype \ intl \ unicharutil \ + docshell \ + shistory \ $(NULL) CPPSRCS = nsWebBrowserPersist.cpp \ diff --git a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp index 4e1d8a30e05a..28b1ad971891 100644 --- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp +++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp @@ -40,6 +40,7 @@ #include "nsIHttpChannel.h" #include "nsIEncodedChannel.h" #include "nsIUploadChannel.h" +#include "nsICachingChannel.h" #include "nsEscape.h" #include "nsUnicharUtils.h" #include "nsCRT.h" @@ -61,6 +62,8 @@ #include "nsIWebProgressListener.h" #include "nsIAuthPrompt.h" #include "nsIPrompt.h" +#include "nsISHEntry.h" +#include "nsIWebPageDescriptor.h" #include "nsIDOMNodeFilter.h" #include "nsIDOMProcessingInstruction.h" @@ -336,9 +339,11 @@ NS_IMETHODIMP nsWebBrowserPersist::SetProgressListener( return NS_OK; } -/* void saveURI (in nsIURI aURI, in string aFileName); */ +/* void saveURI (in nsIURI aURI, in nsIURI aReferrer, + in nsIInputStream aPostData, in wstring aExtraHeaders, + in nsISupports aFile); */ NS_IMETHODIMP nsWebBrowserPersist::SaveURI( - nsIURI *aURI, nsIInputStream *aPostData, nsISupports *aFile) + nsIURI *aURI, nsISupports *aCacheKey, nsIURI *aReferrer, nsIInputStream *aPostData, const char *aExtraHeaders, nsISupports *aFile) { NS_ENSURE_TRUE(mFirstAndOnlyUse, NS_ERROR_FAILURE); mFirstAndOnlyUse = PR_FALSE; // Stop people from reusing this object! @@ -348,10 +353,9 @@ NS_IMETHODIMP nsWebBrowserPersist::SaveURI( rv = GetValidURIFromObject(aFile, getter_AddRefs(fileAsURI)); NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_ARG); - return SaveURIInternal(aURI, aPostData, fileAsURI, PR_FALSE); + return SaveURIInternal(aURI, aCacheKey, aReferrer, aPostData, aExtraHeaders, fileAsURI, PR_FALSE); } - /* void saveDocument (in nsIDOMDocument aDocument, in nsIURI aFileURI, in nsIURI aDataPathURI, in string aOutputContentType, in unsigned long aEncodingFlags, in unsigned long aWrapColumn); */ @@ -1070,7 +1074,9 @@ nsresult nsWebBrowserPersist::AppendPathToURI(nsIURI *aURI, const nsAString & aP } nsresult nsWebBrowserPersist::SaveURIInternal( - nsIURI *aURI, nsIInputStream *aPostData, nsIURI *aFile, PRBool aCalcFileExt) + nsIURI *aURI, nsISupports *aCacheKey, nsIURI *aReferrer, + nsIInputStream *aPostData, const char *aExtraHeaders, + nsIURI *aFile, PRBool aCalcFileExt) { NS_ENSURE_ARG_POINTER(aURI); NS_ENSURE_ARG_POINTER(aFile); @@ -1089,6 +1095,34 @@ nsresult nsWebBrowserPersist::SaveURIInternal( loadFlags |= nsIRequest::LOAD_FROM_CACHE; } + // Extract the cache key + nsCOMPtr cacheKey; + if (aCacheKey) + { + // Test if the cache key is actually a web page descriptor (docshell) + nsCOMPtr webPageDescriptor = do_QueryInterface(aCacheKey); + if (webPageDescriptor) + { + nsCOMPtr currentDescriptor; + webPageDescriptor->GetCurrentDescriptor(getter_AddRefs(currentDescriptor)); + if (currentDescriptor) + { + // Descriptor is actually a session history entry + nsCOMPtr shEntry = do_QueryInterface(currentDescriptor); + NS_ASSERTION(shEntry, "The descriptor is meant to be a session history entry"); + if (shEntry) + { + shEntry->GetCacheKey(getter_AddRefs(cacheKey)); + } + } + } + else + { + // Assume a plain cache key + cacheKey = aCacheKey; + } + } + // Open a channel to the URI nsCOMPtr inputChannel; rv = NS_NewChannel(getter_AddRefs(inputChannel), aURI, @@ -1111,11 +1145,18 @@ nsresult nsWebBrowserPersist::SaveURIInternal( } } - // Post data - if (aPostData) + // Set the referrer, post data and headers if any + nsCOMPtr httpChannel(do_QueryInterface(inputChannel)); + if (httpChannel) { - nsCOMPtr httpChannel(do_QueryInterface(inputChannel)); - if (httpChannel) + // Referrer + if (aReferrer) + { + httpChannel->SetReferrer(aReferrer); + } + + // Post data + if (aPostData) { nsCOMPtr stream(do_QueryInterface(aPostData)); if (stream) @@ -1128,6 +1169,48 @@ nsresult nsWebBrowserPersist::SaveURIInternal( uploadChannel->SetUploadStream(aPostData, NS_LITERAL_CSTRING(""), -1); } } + + // Cache key + nsCOMPtr cacheChannel(do_QueryInterface(httpChannel)); + if (cacheChannel && cacheKey) + { + cacheChannel->SetCacheKey(cacheKey); + } + + // Headers + if (aExtraHeaders) + { + nsCAutoString oneHeader; + nsCAutoString headerName; + nsCAutoString headerValue; + PRInt32 crlf = 0; + PRInt32 colon = 0; + const char *kWhitespace = "\b\t\r\n "; + nsCAutoString extraHeaders(aExtraHeaders); + while (PR_TRUE) + { + crlf = extraHeaders.Find("\r\n", PR_TRUE); + if (crlf == -1) + break; + extraHeaders.Mid(oneHeader, 0, crlf); + extraHeaders.Cut(0, crlf + 2); + colon = oneHeader.Find(":"); + if (colon == -1) + break; // Should have a colon + oneHeader.Left(headerName, colon); + colon++; + oneHeader.Mid(headerValue, colon, oneHeader.Length() - colon); + headerName.Trim(kWhitespace); + headerValue.Trim(kWhitespace); + // Add the header (merging if required) + rv = httpChannel->SetRequestHeader(headerName, headerValue, PR_TRUE); + if (NS_FAILED(rv)) + { + EndDownload(NS_ERROR_FAILURE); + return NS_ERROR_FAILURE; + } + } + } } // Add the output transport to the output map with the channel as the key @@ -2117,7 +2200,7 @@ nsWebBrowserPersist::EnumPersistURIs(nsHashKey *aKey, void *aData, void* closure rv = pthis->AppendPathToURI(fileAsURI, data->mFilename); NS_ENSURE_SUCCESS(rv, PR_FALSE); - rv = pthis->SaveURIInternal(uri, nsnull, fileAsURI, PR_TRUE); + rv = pthis->SaveURIInternal(uri, nsnull, nsnull, nsnull, nsnull, fileAsURI, PR_TRUE); // Store the actual object because once it's persisted this // will be fixed up with the right file extension. diff --git a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h index 71f3bf0e2a65..102e9a994b92 100644 --- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h +++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h @@ -74,7 +74,8 @@ protected: nsresult CloneNodeWithFixedUpURIAttributes( nsIDOMNode *aNodeIn, nsIDOMNode **aNodeOut); nsresult SaveURIInternal( - nsIURI *aURI, nsIInputStream *aPostData, nsIURI *aFile, + nsIURI *aURI, nsISupports *aCacheKey, nsIURI *aReferrer, + nsIInputStream *aPostData, const char *aExtraHeaders, nsIURI *aFile, PRBool aCalcFileExt); nsresult SaveDocumentInternal( nsIDOMDocument *aDocument, nsIURI *aFile, nsIURI *aDataPath); diff --git a/embedding/tests/mfcembed/BrowserView.cpp b/embedding/tests/mfcembed/BrowserView.cpp index 0d9ec8e864ba..694abe045fce 100644 --- a/embedding/tests/mfcembed/BrowserView.cpp +++ b/embedding/tests/mfcembed/BrowserView.cpp @@ -690,7 +690,7 @@ void CBrowserView::OnFileSaveAs() if(bSaveAll) persist->SaveDocument(nsnull, file, dataPath, nsnull, 0, 0); else - persist->SaveURI(nsnull, nsnull, file); + persist->SaveURI(nsnull, nsnull, nsnull, nsnull, nsnull, file); } } } @@ -826,7 +826,7 @@ void CBrowserView::OnSaveLinkAs() { nsCOMPtr file; NS_NewNativeLocalFile(nsDependentCString(strFullPath.GetBuffer(0)), TRUE, getter_AddRefs(file)); - persist->SaveURI(linkURI, nsnull, file); + persist->SaveURI(linkURI, nsnull, nsnull, nsnull, nsnull, file); } } } @@ -872,7 +872,7 @@ void CBrowserView::OnSaveImageAs() { nsCOMPtr file; NS_NewNativeLocalFile(nsDependentCString(strFullPath.GetBuffer(0)), TRUE, getter_AddRefs(file)); - persist->SaveURI(linkURI, nsnull, file); + persist->SaveURI(linkURI, nsnull, nsnull, nsnull, nsnull, file); } } } diff --git a/xpfe/communicator/resources/content/contentAreaUtils.js b/xpfe/communicator/resources/content/contentAreaUtils.js index 5508a6614a48..d063b166815c 100644 --- a/xpfe/communicator/resources/content/contentAreaUtils.js +++ b/xpfe/communicator/resources/content/contentAreaUtils.js @@ -371,7 +371,7 @@ function foundHeaderInfo(aSniffer, aData) persistArgs.contentType, encodingFlags, kWrapColumn); } else { dl.init(source, persistArgs.target, null, null, null, persist); - persist.saveURI(source, persistArgs.postData, persistArgs.target); + persist.saveURI(source, null, null, persistArgs.postData, null, persistArgs.target); } }