diff --git a/camino/src/browser/BrowserContentViews.mm b/camino/src/browser/BrowserContentViews.mm index e5ef1165844..80443724028 100644 --- a/camino/src/browser/BrowserContentViews.mm +++ b/camino/src/browser/BrowserContentViews.mm @@ -150,7 +150,7 @@ // match the size to avoid taking the hit of resizing it when it's // not visible. [mCurrentContentView setFrame:browserRect]; - NSLog(@"resizing to %f %f", browserRect.size.width, browserRect.size.height); + // NSLog(@"resizing to %f %f", browserRect.size.width, browserRect.size.height); } diff --git a/camino/src/download/ProgressViewController.mm b/camino/src/download/ProgressViewController.mm index 33b137d692e..1b6bcb175ff 100644 --- a/camino/src/download/ProgressViewController.mm +++ b/camino/src/download/ProgressViewController.mm @@ -65,6 +65,7 @@ static NSString *ProgressViewsShouldResize = @"ProgressViewsShouldResize"; - (void)refreshDownloadInfo; - (void)moveProgressBarToCurrentView; - (void)updateButtons; +- (void)launchFileIfAppropriate; @end @@ -306,12 +307,29 @@ static NSString *ProgressViewsShouldResize = @"ProgressViewsShouldResize"; - (void)downloadDidEnd { - mDownloadDone = YES; - mDownloadTime = -[mStartTime timeIntervalSinceNow]; - [mProgressBar stopAnimation:self]; - - [mExpandedCancelButton setEnabled:NO]; - [self refreshDownloadInfo]; + if (!mDownloadDone) // some error conditions can cause this to get called twice + { + mDownloadDone = YES; + mDownloadTime = -[mStartTime timeIntervalSinceNow]; + [mProgressBar stopAnimation:self]; + + [mExpandedCancelButton setEnabled:NO]; + + // get the Finder to update + [[NSWorkspace sharedWorkspace] noteFileSystemChanged:mDestPath]; + + [self refreshDownloadInfo]; + [self launchFileIfAppropriate]; + } +} + +- (void)launchFileIfAppropriate +{ + if (!mIsFileSave && !mUserCancelled && !mDownloadingError) + { + if ([[PreferenceManager sharedInstance] getBooleanPref:"browser.download.autoDispatch" withSuccess:NULL]) + [[NSWorkspace sharedWorkspace] openFile:mDestPath withApplication:nil andDeactivate:NO]; + } } // this handles lots of things. diff --git a/camino/src/download/nsDownloadListener.h b/camino/src/download/nsDownloadListener.h index d3dc4e47aa7..948d29e5cb4 100644 --- a/camino/src/download/nsDownloadListener.h +++ b/camino/src/download/nsDownloadListener.h @@ -59,8 +59,7 @@ class nsDownloadListener : public CHDownloader, public nsIDownload, - public nsIWebProgressListener, - public nsITimerCallback + public nsIWebProgressListener { public: nsDownloadListener(); @@ -70,9 +69,6 @@ public: NS_DECL_NSIDOWNLOAD NS_DECL_NSIWEBPROGRESSLISTENER - // nsITimerCallback - NS_IMETHOD Notify(nsITimer *timer); - public: void InitDialog(); @@ -91,7 +87,6 @@ private: nsCOMPtr mURI; // The URI of our source file. Null if we're saving a complete document. nsCOMPtr mDestination; // Our destination URL. - nsCOMPtr mEndRefreshTimer; // Timer used to update the status to done nsresult mDownloadStatus; // status from last nofication PRInt64 mStartTime; // When the download started PRPackedBool mBypassCache; // Whether we should bypass the cache or not. diff --git a/camino/src/download/nsDownloadListener.mm b/camino/src/download/nsDownloadListener.mm index 7b24a546886..e219f42459f 100644 --- a/camino/src/download/nsDownloadListener.mm +++ b/camino/src/download/nsDownloadListener.mm @@ -59,12 +59,9 @@ nsDownloadListener::nsDownloadListener() nsDownloadListener::~nsDownloadListener() { - // if we go away before the timer fires, cancel it - if (mEndRefreshTimer) - mEndRefreshTimer->Cancel(); } -NS_IMPL_ISUPPORTS_INHERITED3(nsDownloadListener, CHDownloader, nsIDownload, nsIWebProgressListener, nsITimerCallback) +NS_IMPL_ISUPPORTS_INHERITED2(nsDownloadListener, CHDownloader, nsIDownload, nsIWebProgressListener) #pragma mark - @@ -198,16 +195,6 @@ nsDownloadListener::OnProgressChange(nsIWebProgress *aWebProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) { - if (mUserCanceled && !mSentCancel) - { - if (mHelperAppLauncher) - mHelperAppLauncher->Cancel(); - else if (aRequest) - aRequest->Cancel(NS_BINDING_ABORTED); - - mSentCancel = PR_TRUE; - } - [mDownloadDisplay setProgressTo:aCurTotalProgress ofMax:aMaxTotalProgress]; return NS_OK; } @@ -228,6 +215,10 @@ nsDownloadListener::OnStatusChange(nsIWebProgress *aWebProgress, nsresult aStatus, const PRUnichar *aMessage) { + // aMessage contains an error string, but it's so crappy that we don't want to use it. + if (NS_FAILED(aStatus)) + DownloadDone(aStatus); + return NS_OK; } @@ -262,28 +253,6 @@ nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aReq #pragma mark - -// nsITimerCallback implementation -NS_IMETHODIMP nsDownloadListener::Notify(nsITimer *timer) -{ - // resset the destination, since uniquifying the filename may have - // changed it - nsAutoString pathStr; - mDestination->GetPath(pathStr); - NSString* destPath = [NSString stringWith_nsAString:pathStr]; - [mDownloadDisplay setDestinationPath:destPath]; - - // update the Finder immediately. - if ( NS_SUCCEEDED(mDownloadStatus) ) - [[NSWorkspace sharedWorkspace] noteFileSystemChanged:destPath]; - - // cancelling should give us a failure status - [mDownloadDisplay onEndDownload:(NS_SUCCEEDED(mDownloadStatus) && !mUserCanceled)]; - mEndRefreshTimer = NULL; - return NS_OK; -} - -#pragma mark - - void nsDownloadListener::InitDialog() { @@ -337,15 +306,20 @@ nsDownloadListener::CancelDownload() { mUserCanceled = PR_TRUE; - if (mWebPersist && !mSentCancel) + if (!mSentCancel) { - mWebPersist->CancelSave(); + if (mWebPersist) + mWebPersist->CancelSave(); + else if (mHelperAppLauncher) + mHelperAppLauncher->Cancel(); + mSentCancel = PR_TRUE; } - - // delete any files we've created... - - // DownloadDone will get called (eventually) + + // when we cancel the download, we don't get any more notifications + // from the backend (unlike for other transfer errors. So we have + // to call DownloadDone ourselves. + DownloadDone(NS_BINDING_ABORTED); } void @@ -361,21 +335,16 @@ nsDownloadListener::DownloadDone(nsresult aStatus) mHelperAppLauncher = nsnull; mDownloadStatus = aStatus; - // hack alert! - // Our destination file gets uniquified after the OnStop notification is sent - // (in nsExternalAppHandler::ExecuteDesiredAction), so we never get a chance - // to figure out the final filename. To work around this, set a timer to fire - // in the near future, from which we'll send the done callback. - mEndRefreshTimer = do_CreateInstance("@mozilla.org/timer;1"); - if (mEndRefreshTimer) + if (NS_FAILED(aStatus)) { - nsresult rv = mEndRefreshTimer->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT); - if (NS_FAILED(rv)) - mEndRefreshTimer = NULL; + // delete the file we created in CHBrowserService::Show + mDestination->Remove(PR_FALSE); + mDestination = nsnull; } - if (!mEndRefreshTimer) // timer creation or init failed, so just do it now - [mDownloadDisplay onEndDownload:(NS_SUCCEEDED(aStatus) && !mUserCanceled)]; + // XXX propagate the error, so that the UI can show strings for + // disk full etc. + [mDownloadDisplay onEndDownload:(NS_SUCCEEDED(aStatus) && !mUserCanceled)]; } // diff --git a/camino/src/embedding/CHBrowserService.mm b/camino/src/embedding/CHBrowserService.mm index 8f6d392c28d..baf5dacfd0a 100644 --- a/camino/src/embedding/CHBrowserService.mm +++ b/camino/src/embedding/CHBrowserService.mm @@ -47,8 +47,12 @@ #include "nsIGenericFactory.h" #include "nsIComponentRegistrar.h" #include "nsEmbedAPI.h" +#include "nsIURI.h" #include "nsIDownload.h" +#include "nsIDirectoryService.h" +#include "nsDirectoryServiceDefs.h" #include "nsIExternalHelperAppService.h" +#include "nsIMIMEInfo.h" #include "nsIPref.h" NSString* TermEmbeddingNotificationName = @"TermEmbedding"; @@ -63,7 +67,6 @@ PRBool CHBrowserService::sCanTerminate = PR_FALSE; // CHBrowserService implementation CHBrowserService::CHBrowserService() { - NS_INIT_ISUPPORTS(); } CHBrowserService::~CHBrowserService() @@ -227,21 +230,43 @@ CHBrowserService::Show(nsIHelperAppLauncher* inLauncher, nsISupports* inContext) // See if pref enabled to allow automatic download nsCOMPtr prefService (do_GetService(NS_PREF_CONTRACTID)); - if (prefService) { + if (prefService) prefService->GetBoolPref("browser.download.autoDownload", &autoDownload); - } - if (autoDownload) { - // Pref is enabled so just save the file to disk in download folder - // If browser.download.autoDownload is set to true helper app will be called by uriloader - // XXX fix me. When we add UI to enable this pref it needs to be clear it carries - // a security risk - return inLauncher->LaunchWithApplication(nsnull, PR_FALSE); - } - else { - // Pref not enabled so do it old way - prompt to save file to disk - return inLauncher->SaveToDisk(nsnull, PR_FALSE); - } + nsCOMPtr downloadFile; + if (autoDownload) + { + NS_GetSpecialDirectory(NS_MAC_DEFAULT_DOWNLOAD_DIR, getter_AddRefs(downloadFile)); + + nsXPIDLString leafName; + inLauncher->GetSuggestedFileName(getter_Copies(leafName)); + if (leafName.IsEmpty()) + { + nsCOMPtr sourceURI; + inLauncher->GetSource(getter_AddRefs(sourceURI)); + if (sourceURI) + { + // we know this doesn't have a leaf name, because nsExternalAppHandler::SetUpTempFile would have + // got it already. + nsCAutoString hostName; + sourceURI->GetHost(hostName); + leafName = NS_ConvertUTF8toUCS2(hostName); + leafName.Append(NS_LITERAL_STRING(" download")); + } + else + { + leafName.Assign(NS_LITERAL_STRING("Camino download")); + } + } + + downloadFile->Append(leafName); + // this will make an empty file, that persists until the download is done, "holding" + // a file system location for the final file. Note that if you change this, be + // sure to fix nsDownloadListener::DownloadDone not to delete some random file. + downloadFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); + } + + return inLauncher->SaveToDisk(downloadFile, PR_FALSE); } NS_IMETHODIMP