/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: NPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Netscape Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 2002 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the NPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the NPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #import "ProgressDlgController.h" #include "nsCOMPtr.h" #include "nsString.h" #include "nsIWebBrowserPersist.h" #include "nsIInputStream.h" #include "nsIURL.h" #include "nsILocalFile.h" #include "nsIDOMHTMLDocument.h" #include "nsIWebProgressListener.h" #include "nsIComponentManager.h" #include "nsIPrefBranch.h" const char* prefContractID = "@mozilla.org/preferences-service;1"; class nsDownloadListener : public nsIWebProgressListener { public: nsDownloadListener(ProgressDlgController* aController, nsIWebBrowserPersist* aPersist, nsISupports* aSource, NSString* aDestination, const char* aContentType, nsIInputStream* aPostData, BOOL aBypassCache) { NS_INIT_REFCNT(); mController = aController; mWebPersist = aPersist; // The source is either a simple URL or a complete document. mURL = do_QueryInterface(aSource); if (!mURL) mDocument = do_QueryInterface(aSource); nsCAutoString dstStr = [aDestination cString]; NS_NewLocalFile(dstStr, PR_FALSE, getter_AddRefs(mDestination)); mContentType = aContentType; mPostData = aPostData; mBypassCache = aBypassCache; }; virtual ~nsDownloadListener() {}; NS_DECL_ISUPPORTS NS_DECL_NSIWEBPROGRESSLISTENER public: void BeginDownload(); void InitDialog(); private: // Member variables ProgressDlgController* mController; // Controller for our UI. nsCOMPtr mWebPersist; // Our web persist object. nsCOMPtr mURL; // The URL of our source file. Null if we're saving a complete document. nsCOMPtr mDestination; // Our destination URL. nsCString mContentType; // Our content type string. nsCOMPtr mDocument; // A DOM document. Null if we're only saving a simple URL. nsCOMPtr mPostData; // For complete documents, this is our post data from session history. PRBool mBypassCache; // Whether we should bypass the cache or not. }; NS_IMPL_ISUPPORTS1(nsDownloadListener, nsIWebProgressListener) /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */ NS_IMETHODIMP nsDownloadListener::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) { return NS_OK; } /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ NS_IMETHODIMP nsDownloadListener::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) { return NS_OK; } /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */ NS_IMETHODIMP nsDownloadListener::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage) { return NS_OK; } /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long state); */ NS_IMETHODIMP nsDownloadListener::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 state) { return NS_OK; } // Implementation of nsIWebProgressListener /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aStateFlags, in unsigned long aStatus); */ NS_IMETHODIMP nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aStateFlags, PRUint32 aStatus) { return NS_OK; } void nsDownloadListener::BeginDownload() { if (mWebPersist) { mWebPersist->SetProgressListener(this); PRInt32 flags = nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION | nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES; if (mBypassCache) flags |= nsIWebBrowserPersist::PERSIST_FLAGS_BYPASS_CACHE; else flags |= nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE; if (mURL) mWebPersist->SaveURI(mURL, mPostData, mDestination); else { PRInt32 encodingFlags = 0; nsCOMPtr filesFolder; if (!mContentType.Equals("text/plain")) { // 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"); nsCAutoString unicodePath; mDestination->GetPath(unicodePath); filesFolder->InitWithPath(unicodePath); nsCAutoString leafName; filesFolder->GetLeafName(leafName); nsCAutoString nameMinusExt(leafName); PRInt32 index = nameMinusExt.RFind("."); if (index >= 0) nameMinusExt.Left(nameMinusExt, index); nameMinusExt += " Files"; // XXXdwh needs to be localizable! filesFolder->SetLeafName(nameMinusExt); PRBool exists = PR_FALSE; filesFolder->Exists(&exists); if (!exists) filesFolder->Create(nsILocalFile::DIRECTORY_TYPE, 0755); } else encodingFlags |= nsIWebBrowserPersist::ENCODE_FLAGS_FORMATTED | nsIWebBrowserPersist::ENCODE_FLAGS_ABSOLUTE_LINKS | nsIWebBrowserPersist::ENCODE_FLAGS_NOFRAMES_CONTENT; mWebPersist->SaveDocument(mDocument, mDestination, filesFolder, mContentType.get(), encodingFlags, 80); } } InitDialog(); } void nsDownloadListener::InitDialog() { if (!mURL && !mDocument) return; if (mWebPersist) { if (mURL) { nsCAutoString spec; mURL->GetSpec(spec); [mController setSourceURL: spec.get()]; } else { nsAutoString spec; mDocument->GetURL(spec); nsCAutoString spec2; spec2.AssignWithConversion(spec); [mController setSourceURL: spec2.get()]; } } nsCAutoString pathStr; mDestination->GetPath(pathStr); [mController setDestination: pathStr.get()]; } static NSString *SaveFileToolbarIdentifier = @"Save File Dialog Toolbar"; static NSString *CancelToolbarItemIdentifier = @"Cancel Toolbar Item"; static NSString *PauseResumeToolbarItemIdentifier = @"Pause and Resume Toggle Toolbar Item"; static NSString *ShowFileToolbarItemIdentifier = @"Show File Toolbar Item"; static NSString *OpenFileToolbarItemIdentifier = @"Open File Toolbar Item"; static NSString *LeaveOpenToolbarItemIdentifier = @"Leave Open Toggle Toolbar Item"; @interface ProgressDlgController(Private) -(void)setupToolbar; @end @implementation ProgressDlgController -(void)setWebPersist:(nsIWebBrowserPersist*)aPersist source:(nsISupports*)aSource destination:(NSString*)aDestination contentType:(const char*)aContentType postData:(nsIInputStream*)aInputStream bypassCache:(BOOL)aBypassCache { mDownloadListener = new nsDownloadListener(self, aPersist, aSource, aDestination, aContentType, aInputStream, aBypassCache); NS_ADDREF(mDownloadListener); } -(void) setSourceURL: (const char*)aSource { [mFromField setStringValue: [NSString stringWithCString: aSource]]; } -(void) setDestination: (const char*)aDestination { [mToField setStringValue: [NSString stringWithCString: aDestination]]; } - (void)windowDidLoad { mDownloadIsPaused = NO; nsCOMPtr prefs(do_GetService(prefContractID)); PRBool save = PR_FALSE; prefs->GetBoolPref("browser.download.progressDnldDialog.keepAlive", &save); mSaveFileDialogShouldStayOpen = save; [self setupToolbar]; if (mDownloadListener) mDownloadListener->BeginDownload(); } - (void)setupToolbar { NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:SaveFileToolbarIdentifier] autorelease]; [toolbar setDisplayMode:NSToolbarDisplayModeDefault]; [toolbar setAllowsUserCustomization:YES]; [toolbar setAutosavesConfiguration:YES]; [toolbar setDelegate:self]; [[self window] setToolbar:toolbar]; } - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar { return [NSArray arrayWithObjects: CancelToolbarItemIdentifier, PauseResumeToolbarItemIdentifier, ShowFileToolbarItemIdentifier, OpenFileToolbarItemIdentifier, LeaveOpenToolbarItemIdentifier, NSToolbarCustomizeToolbarItemIdentifier, NSToolbarFlexibleSpaceItemIdentifier, NSToolbarSpaceItemIdentifier, NSToolbarSeparatorItemIdentifier, nil]; } - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar { return [NSArray arrayWithObjects: CancelToolbarItemIdentifier, PauseResumeToolbarItemIdentifier, NSToolbarFlexibleSpaceItemIdentifier, LeaveOpenToolbarItemIdentifier, NSToolbarFlexibleSpaceItemIdentifier, ShowFileToolbarItemIdentifier, OpenFileToolbarItemIdentifier, nil]; } - (NSToolbarItem *) toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdent willBeInsertedIntoToolbar:(BOOL)willBeInserted { NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdent] autorelease]; if ( [itemIdent isEqual:CancelToolbarItemIdentifier] ) { [toolbarItem setLabel:@"Cancel"]; [toolbarItem setPaletteLabel:@"Cancel Download"]; [toolbarItem setToolTip:@"Cancel this file download"]; [toolbarItem setImage:[NSImage imageNamed:@"saveCancel"]]; [toolbarItem setTarget:self]; [toolbarItem setAction:@selector(cancel)]; } else if ( [itemIdent isEqual:PauseResumeToolbarItemIdentifier] ) { [toolbarItem setLabel:@"Pause"]; [toolbarItem setPaletteLabel:@"Pause Download"]; [toolbarItem setToolTip:@"Pause this FTP file download"]; [toolbarItem setImage:[NSImage imageNamed:@"savePause"]]; [toolbarItem setTarget:self]; [toolbarItem setAction:@selector(pauseAndResumeDownload)]; if ( willBeInserted ) { pauseResumeToggleToolbarItem = toolbarItem; //establish reference } } else if ( [itemIdent isEqual:ShowFileToolbarItemIdentifier] ) { [toolbarItem setLabel:@"Show File"]; [toolbarItem setPaletteLabel:@"Show File"]; [toolbarItem setToolTip:@"Show the saved file in the Finder"]; [toolbarItem setImage:[NSImage imageNamed:@"saveShowFile"]]; [toolbarItem setTarget:self]; [toolbarItem setAction:@selector(showFile)]; } else if ( [itemIdent isEqual:OpenFileToolbarItemIdentifier] ) { [toolbarItem setLabel:@"Open File"]; [toolbarItem setPaletteLabel:@"Open File"]; [toolbarItem setToolTip:@"Open the saved file in its default application."]; [toolbarItem setImage:[NSImage imageNamed:@"saveOpenFile"]]; [toolbarItem setTarget:self]; [toolbarItem setAction:@selector(openFile)]; } else if ( [itemIdent isEqual:LeaveOpenToolbarItemIdentifier] ) { if ( mSaveFileDialogShouldStayOpen ) { [toolbarItem setLabel:@"Leave Open"]; [toolbarItem setPaletteLabel:@"Toggle Close Behavior"]; [toolbarItem setToolTip:@"Window will stay open when download finishes."]; [toolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenYES"]]; [toolbarItem setTarget:self]; [toolbarItem setAction:@selector(toggleLeaveOpen)]; } else { [toolbarItem setLabel:@"Close When Done"]; [toolbarItem setPaletteLabel:@"Toggle Close Behavior"]; [toolbarItem setToolTip:@"Window will close automatically when download finishes."]; [toolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenNO"]]; [toolbarItem setTarget:self]; [toolbarItem setAction:@selector(toggleLeaveOpen)]; } if ( willBeInserted ) { leaveOpenToggleToolbarItem = toolbarItem; //establish reference } } else { toolbarItem = nil; } return toolbarItem; } -(void)cancel { NSLog(@"Request to cancel download."); } -(void)pauseAndResumeDownload { if ( ! mDownloadIsPaused ) { //Do logic to pause download mDownloadIsPaused = YES; [pauseResumeToggleToolbarItem setLabel:@"Resume"]; [pauseResumeToggleToolbarItem setPaletteLabel:@"Resume Download"]; [pauseResumeToggleToolbarItem setToolTip:@"Resume the paused FTP download"]; [pauseResumeToggleToolbarItem setImage:[NSImage imageNamed:@"saveResume"]]; } else { //Do logic to resume download mDownloadIsPaused = NO; [pauseResumeToggleToolbarItem setLabel:@"Pause"]; [pauseResumeToggleToolbarItem setPaletteLabel:@"Pause Download"]; [pauseResumeToggleToolbarItem setToolTip:@"Pause this FTP file download"]; [pauseResumeToggleToolbarItem setImage:[NSImage imageNamed:@"savePause"]]; } } -(void)showFile { NSLog(@"Request to show file."); } -(void)openFile { NSLog(@"Request to open file."); } -(void)toggleLeaveOpen { if ( ! mSaveFileDialogShouldStayOpen ) { mSaveFileDialogShouldStayOpen = YES; [leaveOpenToggleToolbarItem setLabel:@"Leave Open"]; [leaveOpenToggleToolbarItem setPaletteLabel:@"Toggle Close Behavior"]; [leaveOpenToggleToolbarItem setToolTip:@"Window will stay open when download finishes."]; [leaveOpenToggleToolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenYES"]]; } else { mSaveFileDialogShouldStayOpen = NO; [leaveOpenToggleToolbarItem setLabel:@"Close When Done"]; [leaveOpenToggleToolbarItem setPaletteLabel:@"Toggle Close Behavior"]; [leaveOpenToggleToolbarItem setToolTip:@"Window will close automatically when download finishes."]; [leaveOpenToggleToolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenNO"]]; } nsCOMPtr prefs(do_GetService(prefContractID)); prefs->SetBoolPref("browser.download.progressDnldDialog.keepAlive", mSaveFileDialogShouldStayOpen); } - (void)windowWillClose:(NSNotification *)notification { [self autorelease]; } - (void)dealloc { NS_IF_RELEASE(mDownloadListener); [super dealloc]; } @end