From bd45eaa9a0e22550bbfb8676746f239549d7cc78 Mon Sep 17 00:00:00 2001 From: "brade%netscape.com" Date: Mon, 3 Jun 2002 13:08:27 +0000 Subject: [PATCH] add flag and code to handle serialization of output (one file at a time) so that publishing doesn't fail due to too many logins or similar (bug 138662 and others); r=adamlock, sr=alecf git-svn-id: svn://10.0.0.236/trunk@122547 18797224-902f-48f8-a5cc-f745e15eee43 --- .../public/nsIWebBrowserPersist.idl | 2 + .../src/nsWebBrowserPersist.cpp | 185 ++++++++++++------ .../src/nsWebBrowserPersist.h | 3 + 3 files changed, 132 insertions(+), 58 deletions(-) diff --git a/mozilla/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl b/mozilla/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl index 11ab47e55e2..7695da0b2b0 100644 --- a/mozilla/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl +++ b/mozilla/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl @@ -60,6 +60,8 @@ interface nsIWebBrowserPersist : nsISupports const unsigned long PERSIST_FLAGS_FIXUP_LINKS_TO_DESTINATION = 256; /** Don't do any adjustments to links */ const unsigned long PERSIST_FLAGS_DONT_FIXUP_LINKS = 512; + /** 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. */ attribute unsigned long persistFlags; diff --git a/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp b/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp index 6c8ecb720b0..45c0fab9872 100644 --- a/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp +++ b/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp @@ -255,6 +255,7 @@ NS_IMETHODIMP nsWebBrowserPersist::SetPersistFlags(PRUint32 aPersistFlags) { mPersistFlags = aPersistFlags; mReplaceExisting = (mPersistFlags & PERSIST_FLAGS_REPLACE_EXISTING_FILES) ? PR_TRUE : PR_FALSE; + mSerializingOutput = (mPersistFlags & PERSIST_FLAGS_SERIALIZE_OUTPUT) ? PR_TRUE : PR_FALSE; return NS_OK; } @@ -382,54 +383,7 @@ NS_IMETHODIMP nsWebBrowserPersist::SaveDocument( if (NS_SUCCEEDED(rv) && datapathAsURI) { - // Count how many URIs in the URI map require persisting - PRUint32 urisToPersist = 0; - if (mURIMap.Count() > 0) - { - mURIMap.Enumerate(EnumCountURIsToPersist, &urisToPersist); - } - - if (urisToPersist > 0) - { - // Persist each file in the uri map. The document(s) - // will be saved after the last one of these is saved. - mURIMap.Enumerate(EnumPersistURIs, this); - } - - if (mOutputMap.Count() == 0) - { - // There are no URIs to save, so just save the document(s) - - // State start notification - if (mProgressListener) - { - mProgressListener->OnStateChange(nsnull, nsnull, - nsIWebProgressListener::STATE_START | - nsIWebProgressListener::STATE_IS_NETWORK, - NS_OK); - } - - rv = SaveDocuments(); - if (NS_FAILED(rv)) - EndDownload(rv); - else - { - // local files won't trigger OnStopRequest so we call EndDownload here - PRBool isFile = PR_FALSE; - fileAsURI->SchemeIs("file", &isFile); - if (isFile) - EndDownload(NS_OK); - } - - // State stop notification - if (mProgressListener) - { - mProgressListener->OnStateChange(nsnull, nsnull, - nsIWebProgressListener::STATE_STOP | - nsIWebProgressListener::STATE_IS_NETWORK, - NS_OK); - } - } + rv = SaveGatheredURIs(fileAsURI); } else if (mProgressListener) { @@ -439,7 +393,7 @@ NS_IMETHODIMP nsWebBrowserPersist::SaveDocument( NS_OK); mProgressListener->OnStateChange(nsnull, nsnull, nsIWebProgressListener::STATE_STOP, - NS_OK); + rv); } return rv; @@ -484,6 +438,88 @@ nsWebBrowserPersist::StartUpload(nsIStorageStream *storStream, return NS_OK; } +nsresult +nsWebBrowserPersist::SaveGatheredURIs(nsIURI *aFileAsURI) +{ + nsresult rv = NS_OK; + + // Count how many URIs in the URI map require persisting + PRUint32 urisToPersist = 0; + if (mURIMap.Count() > 0) + { + mURIMap.Enumerate(EnumCountURIsToPersist, &urisToPersist); + } + + if (urisToPersist > 0) + { + // Persist each file in the uri map. The document(s) + // will be saved after the last one of these is saved. + mURIMap.Enumerate(EnumPersistURIs, this); + } + + // if we don't have anything in mOutputMap (added from above enumeration) + // then we build the doc list (SaveDocuments) + if (mOutputMap.Count() == 0) + { + // There are no URIs to save, so just save the document(s) + + // State start notification + PRUint32 addToStateFlags = 0; + if (mProgressListener) + { + if (mJustStartedLoading) + { + addToStateFlags |= nsIWebProgressListener::STATE_IS_NETWORK; + } + mProgressListener->OnStateChange(nsnull, nsnull, + nsIWebProgressListener::STATE_START | addToStateFlags, NS_OK); + } + + rv = SaveDocuments(); + if (NS_FAILED(rv)) + EndDownload(rv); + else if (aFileAsURI) + { + // local files won't trigger OnStopRequest so we call EndDownload here + PRBool isFile = PR_FALSE; + aFileAsURI->SchemeIs("file", &isFile); + if (isFile) + EndDownload(NS_OK); + } + + // State stop notification + if (mProgressListener) + { + mProgressListener->OnStateChange(nsnull, nsnull, + nsIWebProgressListener::STATE_STOP | addToStateFlags, rv); + } + } + + return rv; +} + +// this method returns true if there is another file to persist and false if not +PRBool +nsWebBrowserPersist::SerializeNextFile() +{ + if (!mSerializingOutput) + { + return PR_FALSE; + } + + nsresult rv = SaveGatheredURIs(nsnull); + if (NS_FAILED(rv)) + { + return PR_FALSE; + } + + return (mURIMap.Count() + || mUploadList.Count() + || mDocList.Count() + || mOutputMap.Count()); +} + + //***************************************************************************** // nsWebBrowserPersist::nsIRequestObserver //***************************************************************************** @@ -552,6 +588,7 @@ NS_IMETHODIMP nsWebBrowserPersist::OnStartRequest( mOutputMap.Remove(&key); // cancel; we don't need to know any more + // stop request will get called request->Cancel(NS_BINDING_ABORTED); } } @@ -581,18 +618,28 @@ NS_IMETHODIMP nsWebBrowserPersist::OnStopRequest( mUploadList.Remove(&key); } } - if (mOutputMap.Count() == 0 && !mCancel && !mStartSaving) + + // ensure we call SaveDocuments if we: + // 1) aren't canceling + // 2) we haven't triggered the save (which we only want to trigger once) + // 3) we aren't serializing (which will call it inside SerializeNextFile) + if (mOutputMap.Count() == 0 && !mCancel && !mStartSaving + && !mSerializingOutput) { - mStartSaving = PR_TRUE; nsresult rv = SaveDocuments(); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); } PRBool completed = PR_FALSE; - if (mOutputMap.Count() == 0 && (mUploadList.Count() == 0) - && mDocList.Count() == 0) + if (mOutputMap.Count() == 0 && mUploadList.Count() == 0) { - completed = PR_TRUE; + // if no documents left in mDocList, --> done + // if we have no files left to serialize and no error result, --> done + if (mDocList.Count() == 0 + || (!SerializeNextFile() && NS_SUCCEEDED(mPersistResult))) + { + completed = PR_TRUE; + } } if (completed) @@ -700,11 +747,15 @@ NS_IMETHODIMP nsWebBrowserPersist::OnDataAvailable( PRInt32 channelContentLength = -1; if (!cancel && - NS_SUCCEEDED(channel->GetContentLength(&channelContentLength)) && - channelContentLength != -1) + NS_SUCCEEDED(channel->GetContentLength(&channelContentLength))) { - if ((channelContentLength - (aOffset + aLength)) == 0) + // if we get -1 at this point, we didn't get content-length header + // assume that we got all of the data and push what we have; + // that's the best we can do now + if ((-1 == channelContentLength) || + ((channelContentLength - (aOffset + aLength)) == 0)) { + NS_ASSERTION(channelContentLength != -1, "no content length"); // we're done with this pass; see if we need to do upload nsCAutoString contentType; channel->GetContentType(contentType); @@ -1371,6 +1422,8 @@ nsresult nsWebBrowserPersist::SaveDocuments() { nsresult rv = NS_OK; + mStartSaving = PR_TRUE; + // Iterate through all queued documents, saving them to file and fixing // them up on the way. @@ -1422,6 +1475,10 @@ nsresult nsWebBrowserPersist::SaveDocuments() if (NS_FAILED(rv)) break; + + // if we're serializing, bail after first iteration of loop + if (mSerializingOutput) + break; } // delete, cleanup regardless of errors (bug 132417) @@ -1429,8 +1486,17 @@ nsresult nsWebBrowserPersist::SaveDocuments() { DocData *docData = (DocData *) mDocList.ElementAt(i); delete docData; + if (mSerializingOutput) + { + mDocList.RemoveElementAt(i); + break; + } + } + + if (!mSerializingOutput) + { + mDocList.Clear(); } - mDocList.Clear(); return rv; } @@ -1807,6 +1873,9 @@ nsWebBrowserPersist::EnumPersistURIs(nsHashKey *aKey, void *aData, void* closure NS_ENSURE_SUCCESS(rv, PR_FALSE); + if (pthis->mSerializingOutput) + return PR_FALSE; + return PR_TRUE; } diff --git a/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h b/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h index 6e7cb300404..2c53a407f49 100644 --- a/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h +++ b/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h @@ -129,6 +129,8 @@ private: nsresult FixRedirectedChannelEntry(nsIChannel *aNewChannel); void EndDownload(nsresult aResult = NS_OK); + nsresult SaveGatheredURIs(nsIURI *aFileAsURI); + PRBool SerializeNextFile(); void CalcTotalProgress(); // nsDOMWalkerCallback method @@ -174,6 +176,7 @@ private: PRPackedBool mCompleted; PRPackedBool mStartSaving; PRPackedBool mReplaceExisting; + PRPackedBool mSerializingOutput; PRUint32 mPersistFlags; PRUint32 mPersistResult; PRInt32 mTotalCurrentProgress;