[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677

cblu cblu at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 07:27:57 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit cd88c3cb1964e3a7320acf061aa3624cf50cec73
Author: cblu <cblu at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Mar 7 02:37:25 2003 +0000

    WebFoundation:
    
            Reviewed by trey.
    
    	Added _web_changeFileAttributes:atPath and factored _web_changeFinderAttributes out to its own method.
    
            * Misc.subproj/WebNSFileManagerExtras.h:
            * Misc.subproj/WebNSFileManagerExtras.m:
            (-[NSFileManager _web_changeFinderAttributes:forFileAtPath:]): was _web_createFileAtPath
            (-[NSFileManager _web_changeFileAttributes:atPath:]): call createFileAtPath, then _web_changeFinderAttributes
            (-[NSFileManager _web_createFileAtPath:contents:attributes:]): call changeFileAttributes, then _web_changeFinderAttributes
    
    WebKit:
    
    	Implemented WebDownload API.
    
    	Fixed: 3118355 - Download mechanism that doesn't involve WebDataSource, WebFrame, WebController etc
    	Fixed: 3110173 - add per-request disabling of download decoding, use to turn off when "Open Safe Files" is off
    
            Reviewed by trey, rjw, mjs.
    
            * Downloads.subproj/WebDownload.h: Tweaked comments, added new methods.
            * Downloads.subproj/WebDownload.m:
            (-[WebDownloadPrivate dealloc]): release new objects
            (-[WebDownload initWithRequest:]): was initWithRequest:delegate:, but found that starting the load from the init method made it tricky to do other set up work before the load started.
            (-[WebDownload _initWithLoadingResource:dataSource:]): private init method, "catches up" to load by sending delegate method immediately, doesn't retain the dataSource, uses it for info
            (-[WebDownload loadWithDelegate:]): new, starts load
            (-[WebDownload cancel]): cancel load with no error
            (-[WebDownload path]): simple getter
            (-[WebDownload setPath:]): implement this because WebDownload is the WebDownloadDecisionListener, call _setPath
            (-[WebDownload resource:willSendRequest:]): resource delegate method
            (-[WebDownload resource:didReceiveResponse:]): resource delegate method
            (-[WebDownload resource:didReceiveData:]): resource delegate method, decode and write data, cancel load if error
            (-[WebDownload resourceDidFinishLoading:]): resource delegate method, decode and write data if necessary, end in error if error
            (-[WebDownload resource:didFailLoadingWithError:]): resource delegate method, end in error
            (-[WebDownload _pathWithUniqueFilenameForPath:]): this work was done in _createFileIfNecessary, does what it says
            (-[WebDownload _createFSRefForPath:]): this work was done in _createFileIfNecessary as well, makes fileRefPtr point to a file
            (-[WebDownload _createFileIfNecessary]): creates file, creates temp file if path hasn't been set yet
            (-[WebDownload _decodeHeaderData:dataForkData:resourceForkData:]): call private method
            (-[WebDownload _decodeData:dataForkData:resourceForkData:]): made private, if the download is encoded, ask client if OK to decode
            (-[WebDownload _decodeData:]): hardly changed, don't cancel, just return error
            (-[WebDownload _dataIfDoneBufferingData:]): moved, not changed
            (-[WebDownload _finishDecoding]): hardly changed, don't cancel, just return error
            (-[WebDownload _writeForkData:isDataFork:]): moved, not changed
            (-[WebDownload _writeDataForkData:resourceForkData:]): moved, not changed
            (-[WebDownload _isFileClosed]): new
            (-[WebDownload _fileDidClose:]): new, called by the callback thread, delete file if deleteFile flag is set, report error or end successfully
            (-[WebDownload _closeForkAsync:]): new
            (-[WebDownload _closeForkSync:]): new
            (-[WebDownload _closeFileAsync]): new
            (-[WebDownload _closeFileSync]): new
            (-[WebDownload _deleteFileAsnyc]): new
            (-[WebDownload _closeAndDeleteFileAsync]): new
            (-[WebDownload _cancelWithError:]): kill load if there is one, report error if there is one, close and delete file is not already closed or deleted
            (-[WebDownload _cancelWithErrorCode:]): internal convenienve, calls _cancelWithError
            (-[WebDownload _setPath:]): set path, if we are already saving data to a temp path, move the file and continue downloading
            (-[WebDownload _currentPath]): new
            (-[WebDownload _errorWithCode:]): new
            (-[WebDownload _dataForkReferenceNumber]): added underscore
            (-[WebDownload _setDataForkReferenceNumber:]): added underscore
            (-[WebDownload _resourceForkReferenceNumber]): added underscore
            (-[WebDownload _setResourceForkReferenceNumber:]): added underscore
            (-[WebDownload _areWritesCancelled]): added underscore
            (-[WebDownload _setWritesCancelled:]): added underscore
            (-[WebDownload _encounteredCloseError]): new
            (-[WebDownload _setEncounteredCloseError:]): new
            (WriteCompletionCallback): call underscored methods
            (CloseCompletionCallback): call underscored methods, handle close error, don't delete file
            (DeleteCompletionCallback): call _currentPath
            * Downloads.subproj/WebDownloadPrivate.h:
            * WebView.subproj/WebBaseResourceHandleDelegate.h: renamed handle to resource
            * WebView.subproj/WebBaseResourceHandleDelegate.m: renamed handle to resource
            (-[WebBaseResourceHandleDelegate _releaseResources]): renamed handle to resource
            (-[WebBaseResourceHandleDelegate startLoading:]): renamed handle to resource
            (-[WebBaseResourceHandleDelegate loadWithRequest:]): renamed handle to resource
            (-[WebBaseResourceHandleDelegate setDefersCallbacks:]): renamed handle to resource
            (-[WebBaseResourceHandleDelegate resource:willSendRequest:]): renamed handle to resource
            (-[WebBaseResourceHandleDelegate resource:didReceiveResponse:]): renamed handle to resource, don't handle downloads
            (-[WebBaseResourceHandleDelegate resource:didReceiveData:]): renamed handle to resource, don't handle downloads
            (-[WebBaseResourceHandleDelegate resourceDidFinishLoading:]): renamed handle to resource, don't handle downloads
            (-[WebBaseResourceHandleDelegate resource:didFailLoadingWithError:]): renamed handle to resource, don't handle downloads
            (-[WebBaseResourceHandleDelegate cancelWithError:]): renamed handle to resource, don't handle downloads
            * WebView.subproj/WebController.h: updated comments
            * WebView.subproj/WebController.m:
            (-[WebController setDownloadDelegate:]): call the ivar downloadDelegate, not downloadProgressDelegate
            (-[WebController downloadDelegate]): call the ivar downloadDelegate, not downloadProgressDelegate
            * WebView.subproj/WebControllerPolicyDelegate.h: removed saveFilenameForResponse:andRequest:, handle by WebDownload
            * WebView.subproj/WebControllerPrivate.h: call the ivar downloadDelegate, not downloadProgressDelegate
            * WebView.subproj/WebDefaultPolicyDelegate.m: removed saveFilenameForResponse:andRequest:, handle by WebDownload
            * WebView.subproj/WebMainResourceClient.h: added WebResourceDelegateProxy icar
            * WebView.subproj/WebMainResourceClient.m: remove most download related stuff
            (-[WebMainResourceClient initWithDataSource:]): create a WebResourceDelegateProxy which allows us to change the resource delegate
            (-[WebMainResourceClient dealloc]): release the proxy
            (-[WebMainResourceClient receivedError:complete:]): don't handle downloads
            (-[WebMainResourceClient continueAfterContentPolicy:response:]): pass the load off to the download
            (-[WebMainResourceClient resource:didReceiveResponse:]): don't handle downloads
            (-[WebMainResourceClient resource:didReceiveData:]): don't handle downloads
            (-[WebMainResourceClient resourceDidFinishLoading:]): don't handle downloads
            (-[WebMainResourceClient resource:didFailLoadingWithError:]): don't handle downloads
            (-[WebMainResourceClient startLoading:]): make the proxy the delegate
            (-[WebResourceDelegateProxy setDelegate:]): switches the resource delegate
            (-[WebResourceDelegateProxy resource:willSendRequest:]): forwards message
            (-[WebResourceDelegateProxy resource:didReceiveResponse:]): forwards message
            (-[WebResourceDelegateProxy resource:didReceiveData:]): forwards message
            (-[WebResourceDelegateProxy resourceDidFinishLoading:]): forwards message
            (-[WebResourceDelegateProxy resource:didFailLoadingWithError:]): forwards message
    
    WebBrowser:
    
    	Made WebBrowser use the WebDownload API. Most of the changes involved switching from a WebDataSource to a WebDownload to represent a download.
    
    	Fixed: 3118355 - Download mechanism that doesn't involve WebDataSource, WebFrame, WebController etc
    	Fixed: 3110173 - add per-request disabling of download decoding, use to turn off when "Open Safe Files" is off
    
            Reviewed by trey.
    
            * BrowserWebController.m: Removed savePathForResponse:: because it is handled by the WebDownload API
            * BrowserWebErrorExtras.m: Define WebErrorDomainBrowser in here not in DownloadMonitor.
            * DownloadMonitor.h:
            * DownloadMonitor.m:
            (-[DownloadMonitor _loadDownloadHistory]): call DownloadProgressEntry init method, not class constructor
            (-[DownloadMonitor init]):
            (-[DownloadMonitor download:didStartFromDataSource:]): new WebDownload API, reuse a DownloadProgressEntry if reloading, else create a new one
            (-[DownloadMonitor download:willSendRequest:]): new WebDownload API
            (-[DownloadMonitor download:didReceiveResponse:]): new WebDownload API
            (-[DownloadMonitor download:decidePathWithListener:suggestedFilename:]): new WebDownload API, set path immediately
            (-[DownloadMonitor download:didReceiveDataOfLength:]): new WebDownload API
            (-[DownloadMonitor downloadShouldDecodeEncodedFile:]): new WebDownload API, return YES if "Open Safe Downloads" is enabled
            (-[DownloadMonitor download:didCreateFileAtPath:]): new WebDownload API
            (-[DownloadMonitor downloadDidFinishDownloading:]): new WebDownload API
            (-[DownloadMonitor download:didFailDownloadingWithError:]): new WebDownload API
            (-[DownloadMonitor downloadMayBeOpenedForDataSource:]): use renamed dictionary
            (-[DownloadMonitor setEntry:forReloadingDownload:]):
            * DownloadProgressEntry.h:
            * DownloadProgressEntry.m:
            (-[DownloadProgressEntry _setDownload:]): new, replaces setDataSource
            (-[DownloadProgressEntry dealloc]): release the response
            (-[DownloadProgressEntry setResponse:]): new
            (-[DownloadProgressEntry response]): new
            (-[DownloadProgressEntry filename]): handle the nil path case (a DownloadProgressEntry now will be created before the file exists)
            (-[DownloadProgressEntry setPath:]): added comments
            (-[DownloadProgressEntry fileExists]): handle the nil path
            (-[DownloadProgressEntry open]): assert for nil path
            (-[DownloadProgressEntry stop]): cancel the download
            (-[DownloadProgressEntry reload]): No need to involve all the WebKit machinery to do a download. Phew!
            (-[DownloadProgressEntry reveal]): handle the nil path
            (-[DownloadProgressEntry setDownloadStage:]): don't do anything if the set stage is the same as the current
            (-[DownloadProgressEntry _openDiskCopyFile]): assert for nil path
            (-[DownloadProgressEntry _openInstallerPackage]): assert for nil path
            (-[DownloadProgressEntry autoOpen]): assert for nil path
            (-[DownloadProgressEntry setDone:]): release and set download to nil
            (-[NSFileManager _pathForSingleItemAtPath:]): assert for nil path
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@3772 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog
index 2bcee76..24f6e8c 100644
--- a/WebKit/ChangeLog
+++ b/WebKit/ChangeLog
@@ -1,3 +1,98 @@
+2003-03-06  Chris Blumenberg  <cblu at apple.com>
+
+	Implemented WebDownload API.
+
+	Fixed: 3118355 - Download mechanism that doesn't involve WebDataSource, WebFrame, WebController etc
+	Fixed: 3110173 - add per-request disabling of download decoding, use to turn off when "Open Safe Files" is off
+
+        Reviewed by trey, rjw, mjs.
+
+        * Downloads.subproj/WebDownload.h: Tweaked comments, added new methods.
+        * Downloads.subproj/WebDownload.m:
+        (-[WebDownloadPrivate dealloc]): release new objects
+        (-[WebDownload initWithRequest:]): was initWithRequest:delegate:, but found that starting the load from the init method made it tricky to do other set up work before the load started.
+        (-[WebDownload _initWithLoadingResource:dataSource:]): private init method, "catches up" to load by sending delegate method immediately, doesn't retain the dataSource, uses it for info
+        (-[WebDownload loadWithDelegate:]): new, starts load
+        (-[WebDownload cancel]): cancel load with no error
+        (-[WebDownload path]): simple getter
+        (-[WebDownload setPath:]): implement this because WebDownload is the WebDownloadDecisionListener, call _setPath
+        (-[WebDownload resource:willSendRequest:]): resource delegate method
+        (-[WebDownload resource:didReceiveResponse:]): resource delegate method
+        (-[WebDownload resource:didReceiveData:]): resource delegate method, decode and write data, cancel load if error
+        (-[WebDownload resourceDidFinishLoading:]): resource delegate method, decode and write data if necessary, end in error if error
+        (-[WebDownload resource:didFailLoadingWithError:]): resource delegate method, end in error
+        (-[WebDownload _pathWithUniqueFilenameForPath:]): this work was done in _createFileIfNecessary, does what it says
+        (-[WebDownload _createFSRefForPath:]): this work was done in _createFileIfNecessary as well, makes fileRefPtr point to a file
+        (-[WebDownload _createFileIfNecessary]): creates file, creates temp file if path hasn't been set yet
+        (-[WebDownload _decodeHeaderData:dataForkData:resourceForkData:]): call private method
+        (-[WebDownload _decodeData:dataForkData:resourceForkData:]): made private, if the download is encoded, ask client if OK to decode
+        (-[WebDownload _decodeData:]): hardly changed, don't cancel, just return error
+        (-[WebDownload _dataIfDoneBufferingData:]): moved, not changed
+        (-[WebDownload _finishDecoding]): hardly changed, don't cancel, just return error
+        (-[WebDownload _writeForkData:isDataFork:]): moved, not changed
+        (-[WebDownload _writeDataForkData:resourceForkData:]): moved, not changed
+        (-[WebDownload _isFileClosed]): new
+        (-[WebDownload _fileDidClose:]): new, called by the callback thread, delete file if deleteFile flag is set, report error or end successfully
+        (-[WebDownload _closeForkAsync:]): new
+        (-[WebDownload _closeForkSync:]): new
+        (-[WebDownload _closeFileAsync]): new
+        (-[WebDownload _closeFileSync]): new
+        (-[WebDownload _deleteFileAsnyc]): new
+        (-[WebDownload _closeAndDeleteFileAsync]): new
+        (-[WebDownload _cancelWithError:]): kill load if there is one, report error if there is one, close and delete file is not already closed or deleted
+        (-[WebDownload _cancelWithErrorCode:]): internal convenienve, calls _cancelWithError
+        (-[WebDownload _setPath:]): set path, if we are already saving data to a temp path, move the file and continue downloading
+        (-[WebDownload _currentPath]): new 
+        (-[WebDownload _errorWithCode:]): new
+        (-[WebDownload _dataForkReferenceNumber]): added underscore
+        (-[WebDownload _setDataForkReferenceNumber:]): added underscore
+        (-[WebDownload _resourceForkReferenceNumber]): added underscore
+        (-[WebDownload _setResourceForkReferenceNumber:]): added underscore
+        (-[WebDownload _areWritesCancelled]): added underscore
+        (-[WebDownload _setWritesCancelled:]): added underscore
+        (-[WebDownload _encounteredCloseError]): new
+        (-[WebDownload _setEncounteredCloseError:]): new 
+        (WriteCompletionCallback): call underscored methods
+        (CloseCompletionCallback): call underscored methods, handle close error, don't delete file
+        (DeleteCompletionCallback): call _currentPath
+        * Downloads.subproj/WebDownloadPrivate.h:
+        * WebView.subproj/WebBaseResourceHandleDelegate.h: renamed handle to resource
+        * WebView.subproj/WebBaseResourceHandleDelegate.m: renamed handle to resource
+        (-[WebBaseResourceHandleDelegate _releaseResources]): renamed handle to resource
+        (-[WebBaseResourceHandleDelegate startLoading:]): renamed handle to resource
+        (-[WebBaseResourceHandleDelegate loadWithRequest:]): renamed handle to resource
+        (-[WebBaseResourceHandleDelegate setDefersCallbacks:]): renamed handle to resource
+        (-[WebBaseResourceHandleDelegate resource:willSendRequest:]): renamed handle to resource
+        (-[WebBaseResourceHandleDelegate resource:didReceiveResponse:]): renamed handle to resource, don't handle downloads
+        (-[WebBaseResourceHandleDelegate resource:didReceiveData:]): renamed handle to resource, don't handle downloads
+        (-[WebBaseResourceHandleDelegate resourceDidFinishLoading:]): renamed handle to resource, don't handle downloads
+        (-[WebBaseResourceHandleDelegate resource:didFailLoadingWithError:]): renamed handle to resource, don't handle downloads
+        (-[WebBaseResourceHandleDelegate cancelWithError:]): renamed handle to resource, don't handle downloads
+        * WebView.subproj/WebController.h: updated comments
+        * WebView.subproj/WebController.m: 
+        (-[WebController setDownloadDelegate:]): call the ivar downloadDelegate, not downloadProgressDelegate
+        (-[WebController downloadDelegate]): call the ivar downloadDelegate, not downloadProgressDelegate
+        * WebView.subproj/WebControllerPolicyDelegate.h: removed saveFilenameForResponse:andRequest:, handle by WebDownload
+        * WebView.subproj/WebControllerPrivate.h: call the ivar downloadDelegate, not downloadProgressDelegate
+        * WebView.subproj/WebDefaultPolicyDelegate.m: removed saveFilenameForResponse:andRequest:, handle by WebDownload
+        * WebView.subproj/WebMainResourceClient.h: added WebResourceDelegateProxy icar
+        * WebView.subproj/WebMainResourceClient.m: remove most download related stuff
+        (-[WebMainResourceClient initWithDataSource:]): create a WebResourceDelegateProxy which allows us to change the resource delegate
+        (-[WebMainResourceClient dealloc]): release the proxy
+        (-[WebMainResourceClient receivedError:complete:]): don't handle downloads
+        (-[WebMainResourceClient continueAfterContentPolicy:response:]): pass the load off to the download
+        (-[WebMainResourceClient resource:didReceiveResponse:]): don't handle downloads
+        (-[WebMainResourceClient resource:didReceiveData:]): don't handle downloads
+        (-[WebMainResourceClient resourceDidFinishLoading:]): don't handle downloads
+        (-[WebMainResourceClient resource:didFailLoadingWithError:]): don't handle downloads
+        (-[WebMainResourceClient startLoading:]): make the proxy the delegate
+        (-[WebResourceDelegateProxy setDelegate:]): switches the resource delegate
+        (-[WebResourceDelegateProxy resource:willSendRequest:]): forwards message
+        (-[WebResourceDelegateProxy resource:didReceiveResponse:]): forwards message
+        (-[WebResourceDelegateProxy resource:didReceiveData:]): forwards message
+        (-[WebResourceDelegateProxy resourceDidFinishLoading:]): forwards message
+        (-[WebResourceDelegateProxy resource:didFailLoadingWithError:]): forwards message
+
 2003-03-06  Richard Williamson   <rjw at apple.com>
 
         Move tweaks to WebKit API.
diff --git a/WebKit/Downloads.subproj/WebDownload.h b/WebKit/Downloads.subproj/WebDownload.h
index 8188acc..a14544e 100644
--- a/WebKit/Downloads.subproj/WebDownload.h
+++ b/WebKit/Downloads.subproj/WebDownload.h
@@ -7,6 +7,7 @@
 
 #import <Foundation/Foundation.h>
 
+ at class WebDataSource;
 @class WebDownload;
 @class WebDownloadPrivate;
 @class WebError;
@@ -24,30 +25,37 @@
     @method setPath:
     @abstract This method should be called when the path of the downloaded file has been decided.
     @param path The path of the downloaded file.
+    @discussion If necessary, to avoid overwriting files, "-n" will be appended to the filename before the
+    extension where "n" is a number. Because of this, use the path passed with download:didCreateFileAtPath:
+    on WebDownload when referring to the path of the downloaded file, not the path set with this method.
 */
 -(void)setPath:(NSString *)path;
+
 @end
 
 /*!
     @protocol WebDownloadDelegate
-    @discussion The delegate of a WebDownload must conform to the WebDownloadDelegate protocol.
+    @discussion The delegate of a WebDownload can conform to the WebDownloadDelegate protocol.
     The delegate is primarily used to report the progress of the download. Note: The word "download" is used to
     refer to the process of loading data off a network, decoding the data if necessary and saving the data to a file.
-    The delegate recieves these calls in this order:
-
-    - download:willSendRequest: (called once or more)<BR>
-    - download:didReceiveResponse:<BR>
-    - download:decidePathWithListener:suggestedFilename: (possibly not called)<BR>
-    - download:didReceiveDataOfLength: (called once or more)<BR>
-    - downloadDidFinishLoading: or - download:didFailLoadingWithError:
 */
- at protocol WebDownloadDelegate <NSObject>
+ at interface NSObject (WebDownloadDelegate)
+
+/*!
+    @method download:startedFromDataSource:
+    @abstract This method is called immediately after the download has started.
+    @discussion A download is started from a data source if the WebPolicySave WebPolicyAction was chosen for a request.
+    @param download The download that just started downloading.
+    @param response The data source that the download started from. Nil if the download was not started from a data source.
+ */
+- (void)download:(WebDownload *)download didStartFromDataSource:(WebDataSource *)dataSource;
+
 /*!
     @method download:willSendRequest:
     @abstract This method is called whenever the download is about to load a request or if the download
     must load another request because the previous request was redirected.
-    @discussion This method is always initially called with a copy of the request that was passed with
-    initWithRequest:delegate:. This method gives the delegate an opportunity to inspect the request
+    @discussion This method is called with a copy of the request that was passed with
+    initWithRequest:. This method gives the delegate an opportunity to inspect the request
     that will be used to continue loading the request, and modify it if necessary.
     @param download The download that will send the request.
     @param request The request that will be used to continue loading.
@@ -57,8 +65,8 @@
 
 /*!
     @method download:didReceiveResponse:
-    @abstract This method is called when the download has received enough information to contruct a WebResourceResponse.
-    @param download The download that now has a WebResourceResponse available for inspection.
+    @abstract This method is called when the download has received enough information to contruct a WebResponse.
+    @param download The download that now has a WebResponse available for inspection.
     @param response The WebResourceResponse object for the given download.
 */
 - (void)download:(WebDownload *)download didReceiveResponse:(WebResponse *)response;
@@ -86,23 +94,44 @@
 - (void)download:(WebDownload *)download didReceiveDataOfLength:(unsigned)length;
 
 /*!
-    @method downloadDidFinishLoading:
+    @method downloadShouldDecodeEncodedFile:
+    @abstract This method is called if the download detects that the downloading file is encoded.
+    @discussion An encoded file is encoded in MacBinary, BinHex or gzip format.
+    This method is not called if the download is not encoded.
+    @param download The download that has detected that the downloading file is encoded.
+    @result Return YES to decode the file, NO to not decode the file.
+*/
+- (BOOL)downloadShouldDecodeEncodedFile:(WebDownload *)download;
+
+/*!
+    @method download:didCreatedFileAtPath:
+    @abstract This method is called after the download creates the download file.
+    @discussion The filename of path may be different than the path set with setPath:
+    so the download does not overwrite an existing file.
+    @param download The download that created the downloading file.
+    @param path The path of the downloading file.
+*/
+- (void)download:(WebDownload *)download didCreateFileAtPath:(NSString *)path;
+
+/*!
+    @method downloadDidFinishDownloading:
     @abstract This method is called when the download has finished downloading.
     @discussion This method is called after all the data has been received and written to disk.
-    This method or download:didFailLoadingWithError: will only be called once.
+    This method or download:didFailDownloadingWithError: will only be called once.
     @param download The download that has finished downloading.
 */
-- (void)downloadDidFinishLoading:(WebDownload *)download;
+- (void)downloadDidFinishDownloading:(WebDownload *)download;
 
 /*!
-    @method download:didFailLoadingWithError:
+    @method download:didFailDownloadingWithError:
     @abstract This method is called when the download has failed. 
     @discussion This method is called when the download encounters a network or file I/O related error.
-    This method or downloadDidFinishLoading: will only be called once.
+    This method or downloadDidFinishDownloading: will only be called once.
     @param download The download that ended in error.
     @param error The error caused the download to fail.
 */
-- (void)download:(WebDownload *)download didFailLoadingWithError:(WebError *)error;
+- (void)download:(WebDownload *)download didFailDownloadingWithError:(WebError *)error;
+
 @end
 
 /*!
@@ -118,18 +147,22 @@
 }
 
 /*!
-    @method initWithRequest:delegate:
+    @method initWithRequest:
     @abstract Initializes a WebDownload object.
-    @discussion This method also begins the download.
     @param request The request to download. Must not be nil.
+*/
+- initWithRequest:(WebRequest *)request;
+
+/*!
+    @method loadWithDelegate:
+    @abstract Starts the download.
     @param delegate The delegate of the download. Must not be nil.
 */
-- initWithRequest:(WebRequest *)request delegate:(id <WebDownloadDelegate>)delegate;
+- (void)loadWithDelegate:(id)delegate;
 
 /*!
     @method cancel
     @abstract Cancels the download and deletes the downloaded file.
-    @discussion Has no effect after the download has completed.
 */
 - (void)cancel;
 
diff --git a/WebKit/Downloads.subproj/WebDownload.m b/WebKit/Downloads.subproj/WebDownload.m
index efee4db..d8d081e 100644
--- a/WebKit/Downloads.subproj/WebDownload.m
+++ b/WebKit/Downloads.subproj/WebDownload.m
@@ -3,12 +3,13 @@
 //  WebKit
 //
 //  Created by Chris Blumenberg on Thu Apr 11 2002.
-//  Copyright (c) 2002 Apple Computer, Inc.
+//  Copyright (c) 2003 Apple Computer, Inc.
 //
 
 #import <WebKit/WebDownloadPrivate.h>
 
 #import <WebKit/WebBinHexDecoder.h>
+#import <WebKit/WebController.h>
 #import <WebKit/WebDataSourcePrivate.h>
 #import <WebKit/WebDownloadDecoder.h>
 #import <WebKit/WebGZipDecoder.h>
@@ -16,18 +17,19 @@
 #import <WebKit/WebKitLogging.h>
 #import <WebKit/WebMacBinaryDecoder.h>
 #import <WebKit/WebNSWorkspaceExtras.h>
+#import <WebKit/WebResourceResponseExtras.h>
 
 #import <WebFoundation/WebError.h>
 #import <WebFoundation/WebNSFileManagerExtras.h>
 #import <WebFoundation/WebNSStringExtras.h>
 #import <WebFoundation/WebRequest.h>
+#import <WebFoundation/WebResource.h>
 #import <WebFoundation/WebResponse.h>
 
 typedef struct WebFSForkIOParam
 {
     FSForkIOParam paramBlock;
     WebDownload *download;
-    BOOL deleteFile;
     NSData *data;
 } WebFSForkIOParam;
 
@@ -40,52 +42,107 @@ typedef struct WebFSRefParam
 @interface WebDownloadPrivate : NSObject
 {
 @public
-    WebDataSource *dataSource;
-
-    NSArray *decoderClasses;
     NSMutableArray *decoderSequence;
     NSMutableData *bufferedData;
 
-    FSRef fileRef;
     FSRefPtr fileRefPtr;
 
     SInt16 dataForkRefNum;
     SInt16 resourceForkRefNum;
 
-    // isCancelled is used to make sure we don't write after cancelling the load.
-    BOOL isCancelled;
-
-    // areWritesCancelled is only used by WriteCompletionCallback to make
-    // sure that only 1 write failure cancels the load.
+    BOOL deleteFile;
+    BOOL isLoading;
     BOOL areWritesCancelled;
+    BOOL encounteredCloseError;
+
+    WebResource *resource;
+    WebRequest *request;
+    WebResponse *response;
+
+    id delegate;
+
+    NSString *path;
+    NSString *tempPath;
 }
 @end
 
+static NSArray *decoderClasses = nil;
+
 static void WriteCompletionCallback(ParmBlkPtr paramBlock);
 static void CloseCompletionCallback(ParmBlkPtr paramBlock);
 static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
 
+ at interface WebDownload (ForwardDeclarations)
+#pragma mark CREATING
+- (NSString *)_pathWithUniqueFilenameForPath:(NSString *)path;
+- (BOOL)_createFSRefForPath:(NSString *)path;
+- (BOOL)_createFileIfNecessary;
+#pragma mark DECODING
+- (void)_decodeHeaderData:(NSData *)headerData dataForkData:(NSData **)dataForkData resourceForkData:(NSData **)resourceForkData;
+- (BOOL)_decodeData:(NSData *)data dataForkData:(NSData **)dataForkData resourceForkData:(NSData **)resourceForkData;
+- (WebError *)_decodeData:(NSData *)data;
+- (NSData *)_dataIfDoneBufferingData:(NSData *)data;
+- (BOOL)_finishDecoding;
+#pragma mark WRITING
+- (BOOL)_writeForkData:(NSData *)data isDataFork:(BOOL)isDataFork;
+- (WebError *)_writeDataForkData:(NSData *)dataForkData resourceForkData:(NSData *)resourceForkData;
+#pragma mark CLOSING;
+- (BOOL)_isFileClosed;
+- (void)_didCloseFile:(WebError *)error;
+- (void)_closeForkAsync:(SInt16)forkRefNum;
+- (BOOL)_closeForkSync:(SInt16)forkRefNum;
+- (void)_closeFileAsync;
+- (BOOL)_closeFileSync;
+#pragma mark DELETING
+- (void)_didDeleteFile;
+- (void)_deleteFileAsnyc;
+- (void)_closeAndDeleteFileAsync;
+- (void)_cancelWithError:(WebError *)error;
+- (void)_cancelWithErrorCode:(int)code;
+#pragma mark MISC
+- (NSString *)_currentPath;
+- (WebError *)_errorWithCode:(int)code;
+- (SInt16)_dataForkReferenceNumber;
+- (void)_setDataForkReferenceNumber:(SInt16)forkRefNum;
+- (SInt16)_resourceForkReferenceNumber;
+- (void)_setResourceForkReferenceNumber:(SInt16)forkRefNum;
+- (BOOL)_areWritesCancelled;
+- (void)_setWritesCancelled:(BOOL)cancelled;
+- (BOOL)_encounteredCloseError;
+- (void)_setEncounteredCloseError:(BOOL)encounteredCloseError;
+ at end
+
 @implementation WebDownloadPrivate
 
 - init
 {
     [super init];
-    
-    decoderClasses = [[NSArray arrayWithObjects:
-        [WebBinHexDecoder class],
-        [WebMacBinaryDecoder class],
-        [WebGZipDecoder class],
-        nil] retain];
 
+    if (!decoderClasses) {
+        decoderClasses = [[NSArray arrayWithObjects:
+            [WebBinHexDecoder class],
+            [WebMacBinaryDecoder class],
+            [WebGZipDecoder class],
+            nil] retain];
+    }
+    
     return self;
 }
 
 - (void)dealloc
 {
+    ASSERT(!resource);
+    ASSERT(!delegate);
+
+    free(fileRefPtr);
+    
     [bufferedData release];
-    [dataSource release];
-    [decoderClasses release];
     [decoderSequence release];
+    [request release];
+    [resource release];
+    [response release];
+    [path release];
+    [tempPath release];
     [super dealloc];
 }
 
@@ -93,10 +150,57 @@ static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
 
 @implementation WebDownload
 
-- initWithRequest:(WebRequest *)request delegate:(id <WebDownloadDelegate>)delegate
+- initWithRequest:(WebRequest *)request
+{
+    ASSERT(request);
+    
+    [super init];
+    
+    _private = [[WebDownloadPrivate alloc] init];
+    _private->request = [request retain];
+    
+    _private->resource = [[WebResource alloc] initWithRequest:request];
+    if (!_private->resource) {
+        [self release];
+        return nil;
+    }
+
+    return self;
+}
+
+- _initWithLoadingResource:(WebResource *)resource dataSource:(WebDataSource *)dataSource
 {
     [super init];
-    // FIXME: Implement.
+    
+    _private = [[WebDownloadPrivate alloc] init];
+    _private->resource = [resource retain];
+    _private->request = [[dataSource request] retain];
+    _private->response = [[dataSource response] retain];
+    _private->delegate = [[dataSource _controller] downloadDelegate];
+    _private->isLoading = YES;
+
+    // Replay the delegate methods that would be called in the standalone download case.
+    if ([_private->delegate respondsToSelector:@selector(download:didStartFromDataSource:)]) {
+        [_private->delegate download:self didStartFromDataSource:dataSource];
+    }
+
+    // If the request is altered, cancel the previous resource and start a new one.
+    if ([_private->delegate respondsToSelector:@selector(download:willSendRequest:)]) {
+        WebRequest *request = [_private->delegate download:self willSendRequest:_private->request];
+        if (request != _private->request) {
+            [self cancel];
+            if (request) {
+                _private->resource = [[WebResource alloc] initWithRequest:request];
+                [_private->resource loadWithDelegate:(id <WebResourceDelegate>)self];
+            }
+            return self;
+        }
+    }
+    
+    if ([_private->delegate respondsToSelector:@selector(download:didReceiveResponse:)]) {
+        [_private->delegate download:self didReceiveResponse:_private->response];
+    }
+    
     return self;
 }
 
@@ -106,71 +210,243 @@ static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
     [super dealloc];
 }
 
-- (void)cancel
+- (void)loadWithDelegate:(id)delegate
 {
-    _private->isCancelled = YES;
-    [self cleanUpAfterFailure];
+    if (!_private->isLoading) {
+        _private->delegate = delegate;
+        [_private->resource loadWithDelegate:(id <WebResourceDelegate>)self];
+        _private->isLoading = YES;
+    
+        if ([_private->delegate respondsToSelector:@selector(download:didStartFromDataSource:)]) {
+            [_private->delegate download:self didStartFromDataSource:nil];
+        }
+    }
 }
 
- at end
+- (void)cancel
+{
+    [self _cancelWithError:nil];
+}
 
- at implementation WebDownload (WebPrivate)
+- (NSString *)path
+{
+    return _private->path;
+}
 
-- _initWithLoadingHandle:(WebResource *)handle
-                 request:(WebRequest *)request
-                response:(WebRequest *)response
-                delegate:(id <WebDownloadDelegate>)delegate
+// setPath: is not public. This is the WebDownloadDecisionListener method.
+- (void)setPath:(NSString *)path
 {
-    [super init];
-    // FIXME: Implement.
-    return self;
+    [self _setPath:path];
 }
 
-// FIXME: Remove many of the following methods.
+#pragma mark LOADING
 
-- initWithDataSource:(WebDataSource *)dSource
+- (void)_loadFinished
 {
-    [super init];
+    _private->isLoading = NO;
+    
+    [_private->resource release];
+    _private->resource = nil;
+}
 
-    _private = [[WebDownloadPrivate alloc] init];
-    _private->dataSource = [dSource retain];
+-(WebRequest *)resource:(WebResource *)resource willSendRequest:(WebRequest *)theRequest
+{
+    WebRequest *request = nil;
+    
+    if ([_private->delegate respondsToSelector:@selector(download:willSendRequest:)]) {
+        request = [_private->delegate download:self willSendRequest:theRequest];
+    } else {
+        request = theRequest;
+    }
+    
+    if (!request) {
+        [self _loadFinished];
+    }
 
-    LOG(Download, "Download started for: %@", [[dSource request] URL]);
-    return self;
+    if (_private->request != request) {
+        [_private->request release];
+        _private->request = [request retain];
+    }
+
+    return request;
 }
 
-- (WebError *)receivedData:(NSData *)data
+-(void)resource:(WebResource *)resource didReceiveResponse:(WebResponse *)response
 {
-    ASSERT(data);
+    ASSERT(!_private->response);
+    
+    _private->response = [response retain];
+    if ([_private->delegate respondsToSelector:@selector(download:didReceiveResponse:)]) {
+        [_private->delegate download:self didReceiveResponse:response];
+    }
+}
 
-    return [self decodeData:[self dataIfDoneBufferingData:data]];
+-(void)resource:(WebResource *)resource didReceiveData:(NSData *)data
+{
+    if ([_private->delegate respondsToSelector:@selector(download:didReceiveDataOfLength:)]) {
+        [_private->delegate download:self didReceiveDataOfLength:[data length]];
+    }
+    
+    WebError *error = [self _decodeData:[self _dataIfDoneBufferingData:data]];
+    if (error) {
+        [self _cancelWithError:error];
+    }
 }
 
-- (WebError *)finishedLoading
+-(void)resourceDidFinishLoading:(WebResource *)resource
 {
-    WebError *error = [self decodeData:_private->bufferedData];
+    [self _loadFinished];
+    
+    WebError *error = [self _decodeData:_private->bufferedData];
     [_private->bufferedData release];
     _private->bufferedData = nil;
     if (error) {
-        return error;
+        [self _cancelWithError:error];
+        return;
     }
 
-    if (![self finishDecoding]) {
+    if (![self _finishDecoding]) {
         ERROR("Download decoding failed.");
-        [self cleanUpAfterFailure];
-        return [self errorWithCode:WebKitErrorDownloadDecodingFailedToComplete];
+        [self _cancelWithErrorCode:WebKitErrorDownloadDecodingFailedToComplete];
+        return;
     }
 
-    [self closeFile];
+    [self _closeFileAsync];
+}
 
-    LOG(Download, "Download complete. Saved to: %@", [_private->dataSource downloadPath]);
+-(void)resource:(WebResource *)resource didFailLoadingWithError:(WebError *)error
+{
+    [self _loadFinished];
+    
+    [self _cancelWithError:error];
+}
 
-    return nil;
+#pragma mark CREATING
+
+- (NSString *)_pathWithUniqueFilenameForPath:(NSString *)path
+{
+    // "Fix" the filename of the path.
+    NSString *filename = [[path lastPathComponent] _web_filenameByFixingIllegalCharacters];
+    path = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:filename];
+        
+    NSFileManager *fileManager = [NSFileManager defaultManager];
+    if ([fileManager fileExistsAtPath:path]) {
+        // Don't overwrite existing files by appending "-n" or "-n.ext" to the filename.
+        NSString *pathWithoutExtension = [path stringByDeletingPathExtension];
+        NSString *extension = [path pathExtension];
+        NSString *pathWithAppendedNumber;
+        unsigned i;
+
+        for (i = 1; 1; i++) {
+            pathWithAppendedNumber = [NSString stringWithFormat:@"%@-%d", pathWithoutExtension, i];
+            if (extension && [extension length]) {
+                path = [pathWithAppendedNumber stringByAppendingPathExtension:extension];
+            } else {
+                path = pathWithAppendedNumber;
+            }
+            if (![fileManager fileExistsAtPath:path]) {
+                break;
+            }
+        }
+    }
+
+    return path;
+}
+
+- (BOOL)_createFSRefForPath:(NSString *)path
+{
+    free(_private->fileRefPtr);    
+    _private->fileRefPtr = malloc(sizeof(FSRef));
+    
+    OSErr result = FSPathMakeRef((const UInt8 *)[path fileSystemRepresentation], _private->fileRefPtr, NULL);
+    if (result != noErr) {
+        ERROR("FSPathMakeRef failed.");
+        free(_private->fileRefPtr);
+        _private->fileRefPtr = NULL;
+        return NO;
+    }
+
+    return YES;
+}
+
+- (BOOL)_createFileIfNecessary
+{
+    if (_private->fileRefPtr) {
+        // File is already created.
+        return YES;
+    }
+
+    NSObject <WebDownloadDecoder> *lastDecoder = [_private->decoderSequence lastObject];
+    NSMutableDictionary *attributes = [[lastDecoder fileAttributes] mutableCopy];
+    NSFileManager *fileManager = [NSFileManager defaultManager];
+
+    if (!attributes) {
+        attributes = [[NSMutableDictionary alloc] init];
+    }
+    if (![attributes objectForKey:NSFileCreationDate]) {
+        [attributes setObject:[_private->response createdDate] forKey:NSFileCreationDate];
+    }
+    if (![attributes objectForKey:NSFileModificationDate]) {
+        [attributes setObject:[_private->response createdDate] forKey:NSFileModificationDate];
+    }
+
+    // Check if the path is predetermined. If not, ask for one.
+    if (!_private->path) {
+        NSString *filename = [[lastDecoder filename] _web_filenameByFixingIllegalCharacters];
+        if ([filename length] == 0) {
+            filename = [_private->response suggestedFilenameForSaving];
+        }
+
+        if ([_private->delegate respondsToSelector:@selector(download:decidePathWithListener:suggestedFilename:)]) {
+            [_private->delegate download:self
+                  decidePathWithListener:(id <WebDownloadDecisionListener>)self
+                       suggestedFilename:filename];
+        }
+    }
+
+    NSString *path = nil;
+    if (_private->path) {
+        // Path was immeditately set.
+        path = _private->path;
+    } else {
+        // Path wasn't immeditately set. Create the file in /tmp.
+        // FIXME: Consider downloading the file to the default download directory or some other location.
+        char *pathC = strdup("/tmp/WebKitDownload.XXXXXX");
+        if (mktemp(pathC)) {
+            _private->tempPath = [[NSString alloc] initWithCString:pathC];
+            path = _private->tempPath;
+        }
+        free(pathC);
+        if (!path) {
+            ERROR("mktemp failed to create a unique filename in /tmp.");
+            return NO;
+        }
+    }
+
+    if (![fileManager _web_createFileAtPath:path contents:nil attributes:attributes]) {
+        ERROR("-[NSFileManager _web_createFileAtPath:contents:attributes:] failed.");
+        return NO;
+    }
+
+    if (![self _createFSRefForPath:path]) {
+        return NO;
+    }
+
+    [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:path];
+
+    if (_private->path && [_private->delegate respondsToSelector:@selector(download:didCreateFileAtPath:)]) {
+        [_private->delegate download:self didCreateFileAtPath:_private->path];
+    }
+    
+    return YES;
 }
 
-- (void)decodeHeaderData:(NSData *)headerData
-            dataForkData:(NSData **)dataForkData
-        resourceForkData:(NSData **)resourceForkData
+
+#pragma mark DECODING
+
+- (void)_decodeHeaderData:(NSData *)headerData
+             dataForkData:(NSData **)dataForkData
+         resourceForkData:(NSData **)resourceForkData
 {
     ASSERT(headerData);
     ASSERT([headerData length]);
@@ -178,9 +454,9 @@ static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
     ASSERT(resourceForkData);
 
     unsigned i;
-    for (i = 0; i < [_private->decoderClasses count]; i++) {
-        Class decoderClass = [_private->decoderClasses objectAtIndex:i];
-
+    for (i = 0; i < [decoderClasses count]; i++) {
+        Class decoderClass = [decoderClasses objectAtIndex:i];
+        
         if ([decoderClass canDecodeHeaderData:headerData]) {
             NSObject <WebDownloadDecoder> *decoder = [[[decoderClass alloc] init] autorelease];
             BOOL didDecode = [decoder decodeData:headerData dataForkData:dataForkData resourceForkData:resourceForkData];
@@ -193,13 +469,13 @@ static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
 
             [_private->decoderSequence addObject:decoder];
 
-            [self decodeHeaderData:*dataForkData dataForkData:dataForkData resourceForkData:resourceForkData];
+            [self _decodeHeaderData:*dataForkData dataForkData:dataForkData resourceForkData:resourceForkData];
             break;
         }
     }
 }
 
-- (BOOL)decodeData:(NSData *)data
+- (BOOL)_decodeData:(NSData *)data
       dataForkData:(NSData **)dataForkData
   resourceForkData:(NSData **)resourceForkData
 {
@@ -210,7 +486,13 @@ static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
 
     if (!_private->decoderSequence) {
         _private->decoderSequence = [[NSMutableArray array] retain];
-        [self decodeHeaderData:data dataForkData:dataForkData resourceForkData:resourceForkData];
+        [self _decodeHeaderData:data dataForkData:dataForkData resourceForkData:resourceForkData];
+
+        if ([_private->decoderSequence count] > 0 &&
+            [_private->delegate respondsToSelector:@selector(downloadShouldDecodeEncodedFile:)] &&
+            ![_private->delegate downloadShouldDecodeEncodedFile:self]) {
+            [_private->decoderSequence removeAllObjects];
+        }
     } else {
         unsigned i;
         for (i = 0; i< [_private->decoderSequence count]; i++) {
@@ -233,128 +515,32 @@ static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
     return YES;
 }
 
-- (void)closeFork:(SInt16)forkRefNum deleteFile:(BOOL)deleteFile
+- (WebError *)_decodeData:(NSData *)data
 {
-    if (forkRefNum) {
-        WebFSForkIOParam *block = malloc(sizeof(WebFSForkIOParam));
-        block->paramBlock.ioCompletion = CloseCompletionCallback;
-        block->paramBlock.forkRefNum = forkRefNum;
-        block->paramBlock.ref = _private->fileRefPtr;
-        block->download = [self retain];
-        block->deleteFile = deleteFile;
-        PBCloseForkAsync(&block->paramBlock);
-    }
-}
-
-- (void)closeFileAndDelete:(BOOL)deleteFile
-{
-    [self closeFork:_private->dataForkRefNum deleteFile:deleteFile];
-    [self closeFork:_private->resourceForkRefNum deleteFile:deleteFile];
-}
-
-- (void)closeFile
-{
-    [self closeFileAndDelete:NO];
-}
-
-- (void)cleanUpAfterFailure
-{
-    [self closeFileAndDelete:YES];
-}
-
-- (WebError *)createFileIfNecessary
-{
-    if (_private->fileRefPtr) {
+    if ([data length] == 0) {
         return nil;
     }
 
-    NSFileManager *fileManager = [NSFileManager defaultManager];
-    NSString *path = [_private->dataSource downloadPath];
-    NSObject <WebDownloadDecoder> *lastDecoder = [_private->decoderSequence lastObject];
-
-    NSString *filename = [[lastDecoder filename] _web_filenameByFixingIllegalCharacters];
-
-    if ([filename length] != 0) {
-        path = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:filename];
-    }
-
-    if ([fileManager fileExistsAtPath:path]) {
-        NSString *pathWithoutExtension = [path stringByDeletingPathExtension];
-        NSString *extension = [path pathExtension];
-        NSString *pathWithAppendedNumber;
-        unsigned i;
-
-        for (i = 1; 1; i++) {
-            pathWithAppendedNumber = [NSString stringWithFormat:@"%@-%d", pathWithoutExtension, i];
-            if (extension && [extension length]) {
-                path = [pathWithAppendedNumber stringByAppendingPathExtension:extension];
-            } else {
-                path = pathWithAppendedNumber;
-            }
-            if (![fileManager fileExistsAtPath:path]) {
-                break;
-            }
-        }
-    }
-
-    [_private->dataSource _setDownloadPath:path];
-
-    NSDictionary *fileAttributes = [lastDecoder fileAttributes];
-    // FIXME: This assumes that if we get any file attributes, they will include the creation
-    // and modification date, which is not necessarily true.
-    if (!fileAttributes) {
-        WebResponse *response = [_private->dataSource response];
-        fileAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
-            [response createdDate], NSFileCreationDate,
-            [response lastModifiedDate], NSFileModificationDate, nil];
-    }
-
-    if (![fileManager _web_createFileAtPath:path contents:nil attributes:fileAttributes]) {
-        ERROR("-[NSFileManager _web_createFileAtPath:contents:attributes:] failed.");
-        return [self errorWithCode:WebKitErrorCannotCreateFile];
-    }
-
-    [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:path];
+    NSData *dataForkData = nil;
+    NSData *resourceForkData = nil;
 
-    OSErr result = FSPathMakeRef((const UInt8 *)[path fileSystemRepresentation], &_private->fileRef, NULL);
-    if (result == noErr) {
-        _private->fileRefPtr = &_private->fileRef;
-    } else {
-        ERROR("FSPathMakeRef failed.");
-        [self cleanUpAfterFailure];
-        return [self errorWithCode:WebKitErrorCannotCreateFile];
+    if (![self _decodeData:data dataForkData:&dataForkData resourceForkData:&resourceForkData]) {
+        ERROR("Download decoding failed.");
+        return [self _errorWithCode:WebKitErrorDownloadDecodingFailedMidStream];
     }
 
-    return nil;
-}
-
-- (WebError *)writeDataForkData:(NSData *)dataForkData resourceForkData:(NSData *)resourceForkData
-{
-    WebError *error = [self createFileIfNecessary];
+    WebError *error = [self _writeDataForkData:dataForkData resourceForkData:resourceForkData];
     if (error) {
         return error;
     }
 
-    BOOL didWrite = YES;
-
-    if ([dataForkData length]) {
-        didWrite = [self writeForkData:dataForkData isDataFork:YES];
-    }
-
-    if (didWrite && [resourceForkData length]) {
-        didWrite = [self writeForkData:resourceForkData isDataFork:NO];
-    }
-
-    if (!didWrite) {
-        [self cleanUpAfterFailure];
-        return [self errorWithCode:WebKitErrorCannotWriteToFile];
-    }
-
     return nil;
 }
 
-- (NSData *)dataIfDoneBufferingData:(NSData *)data
+- (NSData *)_dataIfDoneBufferingData:(NSData *)data
 {
+    ASSERT([data length] > 0);
+    
     if (!_private->bufferedData) {
         _private->bufferedData = [data mutableCopy];
     } else if ([_private->bufferedData length] == 0) {
@@ -369,7 +555,8 @@ static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
         // We've have enough now. Make a copy so we can set bufferedData's length to 0,
         // so we're know we're done buffering.
         data = [[_private->bufferedData copy] autorelease];
-        [_private->bufferedData setLength:0];
+        [_private->bufferedData release];
+        _private->bufferedData = [[NSMutableData alloc] init];
         return data;
     } else {
         // Keep buffering. The header is not big enough to determine the encoding sequence.
@@ -377,30 +564,7 @@ static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
     }
 }
 
-- (WebError *)decodeData:(NSData *)data
-{
-    if ([data length] == 0) {
-        return nil;
-    }
-
-    NSData *dataForkData = nil;
-    NSData *resourceForkData = nil;
-
-    if (![self decodeData:data dataForkData:&dataForkData resourceForkData:&resourceForkData]) {
-        ERROR("Download decoding failed.");
-        [self cleanUpAfterFailure];
-        return [self errorWithCode:WebKitErrorDownloadDecodingFailedMidStream];
-    }
-
-    WebError *error = [self writeDataForkData:dataForkData resourceForkData:resourceForkData];
-    if (error) {
-        return error;
-    }
-
-    return nil;
-}
-
-- (BOOL)finishDecoding
+- (BOOL)_finishDecoding
 {
     NSObject <WebDownloadDecoder> *decoder;
     unsigned i;
@@ -415,26 +579,15 @@ static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
     return YES;
 }
 
-- (NSString *)path
-{
-    return [_private->dataSource downloadPath];
-}
+#pragma mark WRITING
 
-- (BOOL)writeForkData:(NSData *)data isDataFork:(BOOL)isDataFork
+- (BOOL)_writeForkData:(NSData *)data isDataFork:(BOOL)isDataFork
 {
-    ASSERT(!_private->isCancelled);
-    
-    OSErr result;
     SInt16 *forkRefNum = isDataFork ? &_private->dataForkRefNum : &_private->resourceForkRefNum;
-    
+
     if (*forkRefNum == 0) {
         HFSUniStr255 forkName;
-        if (isDataFork) {
-            result = FSGetDataForkName(&forkName);
-        } else {
-            result = FSGetResourceForkName(&forkName);
-        }
-
+        OSErr result = isDataFork ? FSGetDataForkName(&forkName) : FSGetResourceForkName(&forkName);
         if (result != noErr) {
             ERROR("Couldn't get fork name of download file.");
             return NO;
@@ -462,48 +615,249 @@ static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
     return YES;
 }
 
-- (WebError *)errorWithCode:(int)code
+- (WebError *)_writeDataForkData:(NSData *)dataForkData resourceForkData:(NSData *)resourceForkData
 {
-    return [WebError errorWithCode:code
-                          inDomain:WebErrorDomainWebKit
-                        failingURL:[[_private->dataSource _URL] absoluteString]];
+    if (![self _createFileIfNecessary]) {
+        return [self _errorWithCode:WebKitErrorCannotCreateFile];
+    }
+
+    BOOL didWrite = YES;
+
+    if ([dataForkData length]) {
+        didWrite = [self _writeForkData:dataForkData isDataFork:YES];
+    }
+
+    if (didWrite && [resourceForkData length]) {
+        didWrite = [self _writeForkData:resourceForkData isDataFork:NO];
+    }
+
+    if (!didWrite) {
+        [self _closeAndDeleteFileAsync];
+        return [self _errorWithCode:WebKitErrorCannotWriteToFile];
+    }
+
+    return nil;
+}
+
+#pragma mark CLOSING
+
+- (BOOL)_isFileClosed
+{
+    return (_private->dataForkRefNum == 0 && _private->resourceForkRefNum == 0);
+}
+
+- (void)_didCloseFile:(WebError *)error
+{        
+    if (_private->deleteFile) {
+        [self _deleteFileAsnyc];
+    } else if (error) {
+        [self _cancelWithError:error];
+    } else {
+        [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:[self _currentPath]];
+        if ([_private->delegate respondsToSelector:@selector(downloadDidFinishDownloading:)]) {
+            [_private->delegate downloadDidFinishDownloading:self];
+        }
+        _private->delegate = nil;
+    }
+}
+
+- (void)_closeForkAsync:(SInt16)forkRefNum
+{
+    if (forkRefNum) {
+        WebFSForkIOParam *block = malloc(sizeof(WebFSForkIOParam));
+        block->paramBlock.ioCompletion = CloseCompletionCallback;
+        block->paramBlock.forkRefNum = forkRefNum;
+        block->download = [self retain];
+        PBCloseForkAsync(&block->paramBlock);
+    }
+}
+
+- (BOOL)_closeForkSync:(SInt16)forkRefNum
+{
+    if (forkRefNum) {
+        OSErr error = FSCloseFork(forkRefNum);
+        if (error != noErr) {
+            ERROR("FSCloseFork failed to close fork of download file with error %d", error);
+            return NO;
+        }
+    }
+
+    return YES;
+}
+
+- (void)_closeFileAsync
+{
+    [self _closeForkAsync:_private->dataForkRefNum];
+    [self _closeForkAsync:_private->resourceForkRefNum];
+}
+
+- (BOOL)_closeFileSync
+{
+    BOOL result = YES;
+
+    if (![self _closeForkSync:_private->dataForkRefNum]) {
+        result = NO;
+    }
+    
+    if (![self _closeForkSync:_private->resourceForkRefNum]) {
+        result = NO;
+    }
+    
+    _private->dataForkRefNum = 0;
+    _private->resourceForkRefNum = 0;
+
+    return result;
+}
+
+#pragma mark DELETING
+
+- (void)_didDeleteFile
+{
+    [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:[self _currentPath]];
+}
+
+- (void)_deleteFileAsnyc
+{
+    if (_private->fileRefPtr) {
+        WebFSRefParam *deleteBlock = malloc(sizeof(WebFSRefParam));
+        deleteBlock->paramBlock.ioCompletion = DeleteCompletionCallback;
+        deleteBlock->paramBlock.ref = _private->fileRefPtr;
+        deleteBlock->download = [self retain];
+        PBDeleteObjectAsync(&deleteBlock->paramBlock);
+        free(_private->fileRefPtr);
+        _private->fileRefPtr = NULL;
+    }
+}
+
+- (void)_closeAndDeleteFileAsync
+{
+    if ([self _isFileClosed]) {
+        [self _deleteFileAsnyc];
+    } else {
+        [self _closeFileAsync];
+        _private->deleteFile = YES;
+    }
+}
+
+- (void)_cancelWithError:(WebError *)error
+{
+    [_private->resource cancel];
+    [self _loadFinished];
+
+    if (error) {
+        if ([_private->delegate respondsToSelector:@selector(download:didFailDownloadingWithError:)]) {
+            [_private->delegate download:self didFailDownloadingWithError:error];
+        }
+    }
+
+    _private->delegate = nil;
+
+    [self _closeAndDeleteFileAsync];
 }
 
-- (void)cancelWithError:(WebError *)error
+- (void)_cancelWithErrorCode:(int)code
 {
-    [_private->dataSource _stopLoadingWithError:error];
+    [self _cancelWithError:[self _errorWithCode:code]];
 }
 
-- (SInt16)dataForkReferenceNumber
+#pragma mark MISCELLANEOUS
+
+- (void)_setPath:(NSString *)path
+{
+    ASSERT(path);
+    ASSERT(!_private->path);
+    ASSERT([path isAbsolutePath]);
+
+    // Path has already been set.
+    if (_private->path) {
+        return;
+    }
+
+    if (!path || ![path isAbsolutePath]) {
+        ERROR("setPath: cannot be called with a nil or non-absolute path.");
+        [self cancel];
+        return;
+    }
+
+    // Make sure we don't overwrite an existing file.
+    _private->path = [[self _pathWithUniqueFilenameForPath:path] retain];
+
+    // FIXME: Moving the downloading file synchronously may block the main thread for a long time
+    // if the move is across volumes.
+    if (_private->tempPath && ![_private->tempPath isEqualToString:_private->path]) {
+        if (![self _closeFileSync]) {
+            [self _cancelWithErrorCode:WebKitErrorCannotCloseFile];
+            return;
+        }
+        if (![[NSFileManager defaultManager] movePath:_private->tempPath toPath:_private->path handler:nil]) {
+            [self _cancelWithErrorCode:WebKitErrorCannotMoveFile];
+            return;
+        }
+        if (![self _createFSRefForPath:_private->path]) {
+            [self _cancelWithErrorCode:WebKitErrorCannotCreateFile];
+            return;
+        }
+
+        [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:_private->path];
+
+        if ([_private->delegate respondsToSelector:@selector(download:didCreateFileAtPath:)]) {
+            [_private->delegate download:self didCreateFileAtPath:_private->path];
+        }
+    }
+}
+
+- (NSString *)_currentPath
+{
+    return _private->path ? _private->path : _private->tempPath;
+}
+
+- (WebError *)_errorWithCode:(int)code
+{
+    return [WebError errorWithCode:code
+                          inDomain:WebErrorDomainWebKit
+                        failingURL:[[_private->request URL] absoluteString]];
+}
+
+- (SInt16)_dataForkReferenceNumber
 {
     return _private->dataForkRefNum;
 }
 
-- (void)setDataForkReferenceNumber:(SInt16)forkRefNum
+- (void)_setDataForkReferenceNumber:(SInt16)forkRefNum
 {
     _private->dataForkRefNum = forkRefNum;
 }
 
-- (SInt16)resourceForkReferenceNumber
+- (SInt16)_resourceForkReferenceNumber
 {
     return _private->resourceForkRefNum;
 }
 
-- (void)setResourceForkReferenceNumber:(SInt16)forkRefNum
+- (void)_setResourceForkReferenceNumber:(SInt16)forkRefNum
 {
     _private->resourceForkRefNum = forkRefNum;
 }
 
-- (BOOL)areWritesCancelled
+- (BOOL)_areWritesCancelled
 {
     return _private->areWritesCancelled;
 }
 
-- (void)setWritesCancelled:(BOOL)cancelled
+- (void)_setWritesCancelled:(BOOL)cancelled
 {
     _private->areWritesCancelled = cancelled;
 }
 
+- (BOOL)_encounteredCloseError
+{
+    return _private->encounteredCloseError;
+}
+
+- (void)_setEncounteredCloseError:(BOOL)encounteredCloseError
+{
+    _private->encounteredCloseError = encounteredCloseError;
+}
+
 @end
 
 static void WriteCompletionCallback(ParmBlkPtr paramBlock)
@@ -512,12 +866,13 @@ static void WriteCompletionCallback(ParmBlkPtr paramBlock)
     WebFSForkIOParam *block = (WebFSForkIOParam *)paramBlock;
     WebDownload *download = block->download;
     
-    if (block->paramBlock.ioResult != noErr && ![download areWritesCancelled]) {
+    if (block->paramBlock.ioResult != noErr && ![download _areWritesCancelled]) {
         ERROR("Writing to fork of download file failed with error: %d", block->paramBlock.ioResult);
-        [download setWritesCancelled:YES];
-        [download performSelectorOnMainThread:@selector(cancelWithError:)
-                                          withObject:[download errorWithCode:WebKitErrorCannotWriteToFile]
-                                       waitUntilDone:NO];
+        // Prevent multiple errors from being reported by setting the areWritesCancelled boolean.
+        [download _setWritesCancelled:YES];
+        [download performSelectorOnMainThread:@selector(_cancelWithError:)
+                                   withObject:[download _errorWithCode:WebKitErrorCannotWriteToFile]
+                                waitUntilDone:NO];
     }
 
     [download release];
@@ -534,28 +889,19 @@ static void CloseCompletionCallback(ParmBlkPtr paramBlock)
     
     if (block->paramBlock.ioResult != noErr) {
         ERROR("Closing fork of download file failed with error: %d", block->paramBlock.ioResult);
-        // FIXME: Need to report close errors.
+        [download _setEncounteredCloseError:YES];
     }
 
-    if (block->paramBlock.forkRefNum == [download dataForkReferenceNumber]) {
-        [download setDataForkReferenceNumber:0];
+    if (block->paramBlock.forkRefNum == [download _dataForkReferenceNumber]) {
+        [download _setDataForkReferenceNumber:0];
     } else {
-        [download setResourceForkReferenceNumber:0];
-    }
-
-    // Check if both the data fork and resource fork are now closed.
-    if ([download dataForkReferenceNumber] == 0 && [download resourceForkReferenceNumber] == 0) {
-        if (block->deleteFile && block->paramBlock.ref) {
-            WebFSRefParam *deleteBlock = malloc(sizeof(WebFSRefParam));
-            deleteBlock->paramBlock.ioCompletion = DeleteCompletionCallback;
-            deleteBlock->paramBlock.ref = block->paramBlock.ref;
-            deleteBlock->download = [download retain];                
-            PBDeleteObjectAsync(&deleteBlock->paramBlock);
-        } else {
-            [[NSWorkspace sharedWorkspace] performSelectorOnMainThread:@selector(_web_noteFileChangedAtPath:)
-                                                            withObject:[download path]
-                                                         waitUntilDone:NO];
-        }
+        [download _setResourceForkReferenceNumber:0];
+    }
+
+    if ([download _isFileClosed]) {
+        WebError *error = [download _encounteredCloseError] ?
+                          [download _errorWithCode:WebKitErrorCannotCloseFile] : nil;
+        [download performSelectorOnMainThread:@selector(_didCloseFile:) withObject:error waitUntilDone:NO];
     }
     
     [download release];
@@ -572,9 +918,7 @@ static void DeleteCompletionCallback(ParmBlkPtr paramBlock)
     if (block->paramBlock.ioResult != noErr) {
         ERROR("Removal of download file failed with error: %d", block->paramBlock.ioResult);
     } else {
-        [[NSWorkspace sharedWorkspace] performSelectorOnMainThread:@selector(_web_noteFileChangedAtPath:)
-                                                        withObject:[download path]
-                                                     waitUntilDone:NO];
+        [download performSelectorOnMainThread:@selector(_didDeleteFile) withObject:nil waitUntilDone:NO];
     }
     
     [download release];
diff --git a/WebKit/Downloads.subproj/WebDownloadPrivate.h b/WebKit/Downloads.subproj/WebDownloadPrivate.h
index d8099d8..b385894 100644
--- a/WebKit/Downloads.subproj/WebDownloadPrivate.h
+++ b/WebKit/Downloads.subproj/WebDownloadPrivate.h
@@ -11,37 +11,6 @@
 @class WebResource;
 
 @interface WebDownload (WebPrivate)
-- _initWithLoadingHandle:(WebResource *)handle
-                 request:(WebRequest *)request
-                response:(WebRequest *)response
-                delegate:(id <WebDownloadDelegate>)delegate;
-// FIXME: Remove many of the following methods.
-- initWithDataSource:(WebDataSource *)dSource;
-- (WebError *)receivedData:(NSData *)data;
-- (WebError *)finishedLoading;
-- (void)decodeHeaderData:(NSData *)headerData
-            dataForkData:(NSData **)dataForkData
-        resourceForkData:(NSData **)resourceForkData;
-- (BOOL)decodeData:(NSData *)data
-      dataForkData:(NSData **)dataForkData
-  resourceForkData:(NSData **)resourceForkData;
-- (void)closeFork:(SInt16)forkRefNum deleteFile:(BOOL)deleteFile;
-- (void)closeFileAndDelete:(BOOL)deleteFile;
-- (void)closeFile;
-- (void)cleanUpAfterFailure;
-- (WebError *)createFileIfNecessary;
-- (WebError *)writeDataForkData:(NSData *)dataForkData resourceForkData:(NSData *)resourceForkData;
-- (NSData *)dataIfDoneBufferingData:(NSData *)data;
-- (WebError *)decodeData:(NSData *)data;
-- (BOOL)finishDecoding;
-- (NSString *)path;
-- (WebError *)errorWithCode:(int)code;
-- (void)cancelWithError:(WebError *)error;
-- (SInt16)dataForkReferenceNumber;
-- (void)setDataForkReferenceNumber:(SInt16)forkRefNum;
-- (SInt16)resourceForkReferenceNumber;
-- (void)setResourceForkReferenceNumber:(SInt16)forkRefNum;
-- (BOOL)writeForkData:(NSData *)data isDataFork:(BOOL)isDataFork;
-- (BOOL)areWritesCancelled;
-- (void)setWritesCancelled:(BOOL)cancelled;
+- _initWithLoadingResource:(WebResource *)resource dataSource:(WebDataSource *)dataSource;
+- (void)_setPath:(NSString *)path;
 @end
diff --git a/WebKit/WebView.subproj/WebBaseResourceHandleDelegate.h b/WebKit/WebView.subproj/WebBaseResourceHandleDelegate.h
index ca50a89..f7f62f4 100644
--- a/WebKit/WebView.subproj/WebBaseResourceHandleDelegate.h
+++ b/WebKit/WebView.subproj/WebBaseResourceHandleDelegate.h
@@ -18,7 +18,7 @@
 {
 @protected
     WebDataSource *dataSource;
-    WebResource *handle;
+    WebResource *resource;
     WebRequest *request;
 @private
     WebController *controller;
@@ -41,7 +41,6 @@
 
 - resourceLoadDelegate;
 - downloadDelegate;
-- (BOOL)isDownload;
 
 - (void)cancel;
 - (void)cancelQuietly;
diff --git a/WebKit/WebView.subproj/WebBaseResourceHandleDelegate.m b/WebKit/WebView.subproj/WebBaseResourceHandleDelegate.m
index aee3fa1..b8b50e1 100644
--- a/WebKit/WebView.subproj/WebBaseResourceHandleDelegate.m
+++ b/WebKit/WebView.subproj/WebBaseResourceHandleDelegate.m
@@ -33,8 +33,8 @@
     [identifier release];
     identifier = nil;
 
-    [handle release];
-    handle = nil;
+    [resource release];
+    resource = nil;
 
     [controller release];
     controller = nil;
@@ -64,19 +64,19 @@
 
 - (void)startLoading:(WebRequest *)r
 {
-    [handle loadWithDelegate:self];
+    [resource loadWithDelegate:self];
 }
 
 - (BOOL)loadWithRequest:(WebRequest *)r
 {
-    ASSERT(handle == nil);
+    ASSERT(resource == nil);
     
-    handle = [[WebResource alloc] initWithRequest:r];
-    if (!handle) {
+    resource = [[WebResource alloc] initWithRequest:r];
+    if (!resource) {
         return NO;
     }
     if (defersCallbacks) {
-        [handle setDefersCallbacks:YES];
+        [resource setDefersCallbacks:YES];
     }
 
     [self startLoading:r];
@@ -87,7 +87,7 @@
 - (void)setDefersCallbacks:(BOOL)defers
 {
     defersCallbacks = defers;
-    [handle setDefersCallbacks:defers];
+    [resource setDefersCallbacks:defers];
 }
 
 - (BOOL)defersCallbacks
@@ -129,14 +129,9 @@
     return downloadDelegate;
 }
 
-- (BOOL)isDownload
-{
-    return NO;
-}
-
 -(WebRequest *)resource:(WebResource *)h willSendRequest:(WebRequest *)newRequest
 {
-    ASSERT(handle == h);
+    ASSERT(resource == h);
     ASSERT(!reachedTerminalState);
     
     [newRequest setUserAgent:[controller userAgentForURL:[newRequest URL]]];
@@ -182,41 +177,31 @@
 
 -(void)resource:(WebResource *)h didReceiveResponse:(WebResponse *)r
 {
-    ASSERT(handle == h);
+    ASSERT(resource == h);
     ASSERT(!reachedTerminalState);
 
     [r retain];
     [response release];
     response = r;
 
-    if ([self isDownload])
-        [downloadDelegate resource:identifier didReceiveResponse:r fromDataSource:dataSource];
-    else {
-        [dataSource _addResponse: r];
-        [[controller _resourceLoadDelegateForwarder] resource:identifier didReceiveResponse:r fromDataSource:dataSource];
-    }
+    [dataSource _addResponse: r];
+    [[controller _resourceLoadDelegateForwarder] resource:identifier didReceiveResponse:r fromDataSource:dataSource];
 }
 
 - (void)resource:(WebResource *)h didReceiveData:(NSData *)data
 {
-    ASSERT(handle == h);
+    ASSERT(resource == h);
     ASSERT(!reachedTerminalState);
 
-    if ([self isDownload])
-        [downloadDelegate resource:identifier didReceiveContentLength:[data length] fromDataSource:dataSource];
-    else
-        [[controller _resourceLoadDelegateForwarder] resource:identifier didReceiveContentLength:[data length] fromDataSource:dataSource];
+    [[controller _resourceLoadDelegateForwarder] resource:identifier didReceiveContentLength:[data length] fromDataSource:dataSource];
 }
 
 - (void)resourceDidFinishLoading:(WebResource *)h
 {
-    ASSERT(handle == h);
+    ASSERT(resource == h);
     ASSERT(!reachedTerminalState);
 
-    if ([self isDownload])
-        [downloadDelegate resource:identifier didFinishLoadingFromDataSource:dataSource];
-    else
-        [[controller _resourceLoadDelegateForwarder] resource:identifier didFinishLoadingFromDataSource:dataSource];
+    [[controller _resourceLoadDelegateForwarder] resource:identifier didFinishLoadingFromDataSource:dataSource];
 
     ASSERT(currentURL);
     [[WebStandardPanels sharedStandardPanels] _didStopLoadingURL:currentURL inController:controller];
@@ -226,13 +211,10 @@
 
 - (void)resource:(WebResource *)h didFailLoadingWithError:(WebError *)result
 {
-    ASSERT(handle == h);
+    ASSERT(resource == h);
     ASSERT(!reachedTerminalState);
     
-    if ([self isDownload])
-        [downloadDelegate resource:identifier didFailLoadingWithError:result fromDataSource:dataSource];
-    else
-        [[controller _resourceLoadDelegateForwarder] resource:identifier didFailLoadingWithError:result fromDataSource:dataSource];
+    [[controller _resourceLoadDelegateForwarder] resource:identifier didFailLoadingWithError:result fromDataSource:dataSource];
 
     // currentURL may be nil if the request was aborted
     if (currentURL)
@@ -245,18 +227,14 @@
 {
     ASSERT(!reachedTerminalState);
 
-    [handle cancel];
+    [resource cancel];
     
     // currentURL may be nil if the request was aborted
     if (currentURL)
         [[WebStandardPanels sharedStandardPanels] _didStopLoadingURL:currentURL inController:controller];
 
     if (error) {
-        if ([self isDownload]) {
-            [downloadDelegate resource:identifier didFailLoadingWithError:error fromDataSource:dataSource];
-        } else {
-            [[controller _resourceLoadDelegateForwarder] resource:identifier didFailLoadingWithError:error fromDataSource:dataSource];
-        }
+        [[controller _resourceLoadDelegateForwarder] resource:identifier didFailLoadingWithError:error fromDataSource:dataSource];
     }
 
     [self _releaseResources];
diff --git a/WebKit/WebView.subproj/WebController.h b/WebKit/WebView.subproj/WebController.h
index 0ce09ae..f325c6f 100644
--- a/WebKit/WebView.subproj/WebController.h
+++ b/WebKit/WebView.subproj/WebController.h
@@ -146,15 +146,15 @@ extern NSString *WebElementLinkLabelKey;	// NSString of the text within the anch
 
 /*!
     @method setDownloadDelegate:
-    @abstract Set the controller's WebResourceLoadDelegate download delegate.
-    @param delegate The WebResourceLoadDelegate to set as the download delegate.
+    @abstract Set the controller's WebDownloadDelegate.
+    @param delegate The WebDownloadDelegate to set as the download delegate.
 */    
 - (void)setDownloadDelegate: (id)delegate;
 
 /*!
     @method downloadDelegate
-    @abstract Return the controller's WebResourceLoadDelegate download delegate.
-    @result The controller's WebResourceLoadDelegate download delegate.
+    @abstract Return the controller's WebDownloadDelegate.
+    @result The controller's WebDownloadDelegate.
 */    
 - (id)downloadDelegate;
 
diff --git a/WebKit/WebView.subproj/WebController.m b/WebKit/WebView.subproj/WebController.m
index 827b5dc..362bfaf 100644
--- a/WebKit/WebView.subproj/WebController.m
+++ b/WebKit/WebView.subproj/WebController.m
@@ -167,13 +167,13 @@ NSString *WebElementLinkTitleKey = 		@"WebElementLinkTitle";
 
 - (void)setDownloadDelegate: delegate
 {
-    _private->downloadProgressDelegate = delegate;
+    _private->downloadDelegate = delegate;
 }
 
 
 - downloadDelegate
 {
-    return _private->downloadProgressDelegate;
+    return _private->downloadDelegate;
 }
 
 - (void)setContextMenuDelegate: delegate
diff --git a/WebKit/WebView.subproj/WebControllerPolicyDelegate.h b/WebKit/WebView.subproj/WebControllerPolicyDelegate.h
index 46fdad5..de07d81 100644
--- a/WebKit/WebView.subproj/WebControllerPolicyDelegate.h
+++ b/WebKit/WebView.subproj/WebControllerPolicyDelegate.h
@@ -117,18 +117,6 @@ typedef enum {
                                  andRequest:(WebRequest *)request
                                     inFrame:(WebFrame *)frame;
 
-
-/*!
-    @method saveFilenameForResponse:andRequest:
-    @discussion Returns the filename to use for a load that's being saved.
-    @param response The response for the partially loaded content.
-    @param request A WebResourceRequest for the partially loaded content.
-    @result The filename to use to save a loaded resource.
-*/
-- (NSString *)savePathForResponse:(WebResponse *)response
-                       andRequest:(WebRequest *)request;
-
-
 /*!
     @method unableToImplementPolicy:error:forURL:inFrame:
     @discussion Called when a WebPolicy could not be implemented. It is up to the client to display appropriate feedback.
diff --git a/WebKit/WebView.subproj/WebControllerPrivate.h b/WebKit/WebView.subproj/WebControllerPrivate.h
index 19bd75f..c2d3cf5 100644
--- a/WebKit/WebView.subproj/WebControllerPrivate.h
+++ b/WebKit/WebView.subproj/WebControllerPrivate.h
@@ -24,7 +24,7 @@ enum { NumUserAgentStringTypes = WinIE + 1 };
     
     id windowContext;
     id resourceProgressDelegate;
-    id downloadProgressDelegate;
+    id downloadDelegate;
     id contextMenuDelegate;
     id policyDelegate;
     id locationChangeDelegate;
diff --git a/WebKit/WebView.subproj/WebDefaultPolicyDelegate.m b/WebKit/WebView.subproj/WebDefaultPolicyDelegate.m
index c4560a6..4b40ee2 100644
--- a/WebKit/WebView.subproj/WebDefaultPolicyDelegate.m
+++ b/WebKit/WebView.subproj/WebDefaultPolicyDelegate.m
@@ -54,12 +54,6 @@ static WebDefaultPolicyDelegate *sharedDelegate = nil;
     }
 }
 
-- (NSString *)savePathForResponse:(WebResponse *)response
-                       andRequest:(WebRequest *)request
-{
-    return nil;
-}
-
 - (void)decideNavigationPolicyForAction:(NSDictionary *)actionInformation 
 			     andRequest:(WebRequest *)request
 				inFrame:(WebFrame *)frame
diff --git a/WebKit/WebView.subproj/WebLoader.h b/WebKit/WebView.subproj/WebLoader.h
index ca50a89..f7f62f4 100644
--- a/WebKit/WebView.subproj/WebLoader.h
+++ b/WebKit/WebView.subproj/WebLoader.h
@@ -18,7 +18,7 @@
 {
 @protected
     WebDataSource *dataSource;
-    WebResource *handle;
+    WebResource *resource;
     WebRequest *request;
 @private
     WebController *controller;
@@ -41,7 +41,6 @@
 
 - resourceLoadDelegate;
 - downloadDelegate;
-- (BOOL)isDownload;
 
 - (void)cancel;
 - (void)cancelQuietly;
diff --git a/WebKit/WebView.subproj/WebLoader.m b/WebKit/WebView.subproj/WebLoader.m
index aee3fa1..b8b50e1 100644
--- a/WebKit/WebView.subproj/WebLoader.m
+++ b/WebKit/WebView.subproj/WebLoader.m
@@ -33,8 +33,8 @@
     [identifier release];
     identifier = nil;
 
-    [handle release];
-    handle = nil;
+    [resource release];
+    resource = nil;
 
     [controller release];
     controller = nil;
@@ -64,19 +64,19 @@
 
 - (void)startLoading:(WebRequest *)r
 {
-    [handle loadWithDelegate:self];
+    [resource loadWithDelegate:self];
 }
 
 - (BOOL)loadWithRequest:(WebRequest *)r
 {
-    ASSERT(handle == nil);
+    ASSERT(resource == nil);
     
-    handle = [[WebResource alloc] initWithRequest:r];
-    if (!handle) {
+    resource = [[WebResource alloc] initWithRequest:r];
+    if (!resource) {
         return NO;
     }
     if (defersCallbacks) {
-        [handle setDefersCallbacks:YES];
+        [resource setDefersCallbacks:YES];
     }
 
     [self startLoading:r];
@@ -87,7 +87,7 @@
 - (void)setDefersCallbacks:(BOOL)defers
 {
     defersCallbacks = defers;
-    [handle setDefersCallbacks:defers];
+    [resource setDefersCallbacks:defers];
 }
 
 - (BOOL)defersCallbacks
@@ -129,14 +129,9 @@
     return downloadDelegate;
 }
 
-- (BOOL)isDownload
-{
-    return NO;
-}
-
 -(WebRequest *)resource:(WebResource *)h willSendRequest:(WebRequest *)newRequest
 {
-    ASSERT(handle == h);
+    ASSERT(resource == h);
     ASSERT(!reachedTerminalState);
     
     [newRequest setUserAgent:[controller userAgentForURL:[newRequest URL]]];
@@ -182,41 +177,31 @@
 
 -(void)resource:(WebResource *)h didReceiveResponse:(WebResponse *)r
 {
-    ASSERT(handle == h);
+    ASSERT(resource == h);
     ASSERT(!reachedTerminalState);
 
     [r retain];
     [response release];
     response = r;
 
-    if ([self isDownload])
-        [downloadDelegate resource:identifier didReceiveResponse:r fromDataSource:dataSource];
-    else {
-        [dataSource _addResponse: r];
-        [[controller _resourceLoadDelegateForwarder] resource:identifier didReceiveResponse:r fromDataSource:dataSource];
-    }
+    [dataSource _addResponse: r];
+    [[controller _resourceLoadDelegateForwarder] resource:identifier didReceiveResponse:r fromDataSource:dataSource];
 }
 
 - (void)resource:(WebResource *)h didReceiveData:(NSData *)data
 {
-    ASSERT(handle == h);
+    ASSERT(resource == h);
     ASSERT(!reachedTerminalState);
 
-    if ([self isDownload])
-        [downloadDelegate resource:identifier didReceiveContentLength:[data length] fromDataSource:dataSource];
-    else
-        [[controller _resourceLoadDelegateForwarder] resource:identifier didReceiveContentLength:[data length] fromDataSource:dataSource];
+    [[controller _resourceLoadDelegateForwarder] resource:identifier didReceiveContentLength:[data length] fromDataSource:dataSource];
 }
 
 - (void)resourceDidFinishLoading:(WebResource *)h
 {
-    ASSERT(handle == h);
+    ASSERT(resource == h);
     ASSERT(!reachedTerminalState);
 
-    if ([self isDownload])
-        [downloadDelegate resource:identifier didFinishLoadingFromDataSource:dataSource];
-    else
-        [[controller _resourceLoadDelegateForwarder] resource:identifier didFinishLoadingFromDataSource:dataSource];
+    [[controller _resourceLoadDelegateForwarder] resource:identifier didFinishLoadingFromDataSource:dataSource];
 
     ASSERT(currentURL);
     [[WebStandardPanels sharedStandardPanels] _didStopLoadingURL:currentURL inController:controller];
@@ -226,13 +211,10 @@
 
 - (void)resource:(WebResource *)h didFailLoadingWithError:(WebError *)result
 {
-    ASSERT(handle == h);
+    ASSERT(resource == h);
     ASSERT(!reachedTerminalState);
     
-    if ([self isDownload])
-        [downloadDelegate resource:identifier didFailLoadingWithError:result fromDataSource:dataSource];
-    else
-        [[controller _resourceLoadDelegateForwarder] resource:identifier didFailLoadingWithError:result fromDataSource:dataSource];
+    [[controller _resourceLoadDelegateForwarder] resource:identifier didFailLoadingWithError:result fromDataSource:dataSource];
 
     // currentURL may be nil if the request was aborted
     if (currentURL)
@@ -245,18 +227,14 @@
 {
     ASSERT(!reachedTerminalState);
 
-    [handle cancel];
+    [resource cancel];
     
     // currentURL may be nil if the request was aborted
     if (currentURL)
         [[WebStandardPanels sharedStandardPanels] _didStopLoadingURL:currentURL inController:controller];
 
     if (error) {
-        if ([self isDownload]) {
-            [downloadDelegate resource:identifier didFailLoadingWithError:error fromDataSource:dataSource];
-        } else {
-            [[controller _resourceLoadDelegateForwarder] resource:identifier didFailLoadingWithError:error fromDataSource:dataSource];
-        }
+        [[controller _resourceLoadDelegateForwarder] resource:identifier didFailLoadingWithError:error fromDataSource:dataSource];
     }
 
     [self _releaseResources];
diff --git a/WebKit/WebView.subproj/WebMainResourceClient.h b/WebKit/WebView.subproj/WebMainResourceClient.h
index 4e018f8..d5a17f4 100644
--- a/WebKit/WebView.subproj/WebMainResourceClient.h
+++ b/WebKit/WebView.subproj/WebMainResourceClient.h
@@ -14,19 +14,19 @@
 @class WebDownload;
 @class WebDataSource;
 @class WebResource;
+ at class WebResourceDelegateProxy;
 @class WebRequest;
 @class WebResponse;
 
 @interface WebMainResourceClient : WebBaseResourceHandleDelegate
 {
-    WebDownload *download;
     NSMutableData *resourceData;
     int _contentLength; // for logging only
     int _bytesReceived; // for logging only
+    WebResourceDelegateProxy *proxy;
 }
 
 - initWithDataSource:(WebDataSource *)dataSource;
-- (WebDownload *)download;
 - (NSData *)resourceData;
 
 @end
diff --git a/WebKit/WebView.subproj/WebMainResourceClient.m b/WebKit/WebView.subproj/WebMainResourceClient.m
index 2fea522..9ee3901 100644
--- a/WebKit/WebView.subproj/WebMainResourceClient.m
+++ b/WebKit/WebView.subproj/WebMainResourceClient.m
@@ -34,6 +34,13 @@
 
 // FIXME: More that is in common with WebSubresourceClient should move up into WebBaseResourceHandleDelegate.
 
+ at interface WebResourceDelegateProxy : NSObject <WebResourceDelegate>
+{
+    id <WebResourceDelegate> delegate;
+}
+- (void)setDelegate:(id <WebResourceDelegate>)theDelegate;
+ at end
+
 @implementation WebMainResourceClient
 
 - initWithDataSource:(WebDataSource *)ds
@@ -43,16 +50,17 @@
     if (self) {
         resourceData = [[NSMutableData alloc] init];
         [self setDataSource:ds];
+        proxy = [[WebResourceDelegateProxy alloc] init];
+        [proxy setDelegate:self];
     }
 
     return self;
 }
 
 - (void)dealloc
-{
-    ASSERT(download == nil);
-    
+{    
     [resourceData release];
+    [proxy release];
     
     [super dealloc];
 }
@@ -62,27 +70,9 @@
     return resourceData;
 }
 
-- (WebDownload *)download
-{
-    return download;
-}
-
-- (BOOL)isDownload
-{
-    return download != nil;
-}
-
 - (void)receivedError:(WebError *)error complete:(BOOL)isComplete
 {
-    if (download) {
-        ASSERT(isComplete);
-        [download cancel];
-        [download release];
-        download = nil;
-        [dataSource _setPrimaryLoadComplete:YES];
-    } else {
-        [dataSource _receivedError:error complete:isComplete];
-    }
+    [dataSource _receivedError:error complete:isComplete];
 }
 
 - (void)cancel
@@ -180,34 +170,20 @@
         break;
         
     case WebPolicySave:
-	[dataSource _setIsDownloading:YES];
-
-        NSString *path = [dataSource downloadPath];
-        if (path == nil || ![path isAbsolutePath]) {
-            NSString *directory = [dataSource _downloadDirectory];
-            if (directory != nil && [directory isAbsolutePath]) {
-                path = [directory stringByAppendingPathComponent:[r suggestedFilenameForSaving]];
-            } else {
-                id pd = [[dataSource _controller] policyDelegate];
-                
-                if ([pd respondsToSelector: @selector(savePathForResponse:andRequest:)])
-                    path = [pd savePathForResponse:r andRequest:req];
-                // FIXME: Maybe there a cleaner way handle the bad filename case?
-                if (path == nil || ![path isAbsolutePath]) {
-                    ERROR("Nil or non-absolute path returned from savePathForResponse:andRequest:.");
-                    [self stopLoadingForPolicyChange];
-                    return;
-                }
-            }
-
-	    [dataSource _setDownloadPath:path];
-	}
+        ASSERT([self downloadDelegate]);
 
-        [self interruptForPolicyChangeAndKeepLoading:YES];
+        WebDownload *download = [[WebDownload alloc] _initWithLoadingResource:resource dataSource:dataSource];
+        NSString *directory = [dataSource _downloadDirectory];
+        if (directory != nil && [directory isAbsolutePath]) {
+            // FIXME: Predetermined downloads should not be using this code path (3191052).
+            NSString *path = [directory stringByAppendingPathComponent:[r suggestedFilenameForSaving]];
+            [download _setPath:path];
+        }
+
+        [proxy setDelegate:(id <WebResourceDelegate>)download];
+        [download release];
         
-	// Hand off the dataSource to the download handler.  This will cause the remaining
-	// handle delegate callbacks to go to the controller's download delegate.
-	download = [[WebDownload alloc] initWithDataSource:dataSource];
+        [self interruptForPolicyChangeAndKeepLoading:YES];
         break;
 
     case WebPolicyOpenURL:
@@ -245,10 +221,10 @@
         ERROR("contentPolicyForMIMEType:andRequest:inFrame: returned an invalid content policy.");
     }
 
-    [super resource:handle didReceiveResponse:r];
+    [super resource:resource didReceiveResponse:r];
 
     if ([[req URL] _web_shouldLoadAsEmptyDocument]) {
-	[self resourceDidFinishLoading:handle];
+	[self resourceDidFinishLoading:resource];
     }
 }
 
@@ -277,10 +253,11 @@
     ASSERT([dataSource isDownloading] || ![[dataSource _controller] defersCallbacks]);
     [dataSource _setResponse:r];
 
-    LOG(Download, "main content type: %@", [r contentType]);
+    LOG(Loading, "main content type: %@", [r contentType]);
 
     [[dataSource _controller] setDefersCallbacks:YES];
 
+    // FIXME: Predetermined downloads should not be using this code path (3191052).
     // Figure out the content policy.
     if (![dataSource isDownloading]) {
 	[self checkContentPolicyForResponse:r andCallSelector:@selector(continueAfterContentPolicy:response:)];
@@ -297,64 +274,39 @@
     ASSERT([data length] != 0);
     ASSERT(![h defersCallbacks]);
     ASSERT(![self defersCallbacks]);
-    ASSERT([self isDownload] || ![[dataSource _controller] defersCallbacks]);
+    ASSERT(![[dataSource _controller] defersCallbacks]);
  
     LOG(Loading, "URL = %@, data = %p, length %d", [dataSource _URL], data, [data length]);
 
-    WebError *downloadError= nil;
-    
-    if (download) {
-        downloadError = [download receivedData:data];
-    } else {
-        [resourceData appendData:data];
-        [dataSource _receivedData:data];
-        [[dataSource _controller] _mainReceivedBytesSoFar:[resourceData length]
-                                          fromDataSource:dataSource
-                                                complete:NO];
-    }
-    
+    [resourceData appendData:data];
+    [dataSource _receivedData:data];
+    [[dataSource _controller] _mainReceivedBytesSoFar:[resourceData length]
+                                        fromDataSource:dataSource
+                                            complete:NO];
+
     [super resource:h didReceiveData:data];
     _bytesReceived += [data length];
-    
-    if(downloadError){
-        // Cancel download after calling didReceiveData to preserve ordering of calls.
-        [self cancelWithError:downloadError];
-    }
 
-    LOG(Download, "%d of %d", _bytesReceived, _contentLength);
+    LOG(Loading, "%d of %d", _bytesReceived, _contentLength);
 }
 
 - (void)resourceDidFinishLoading:(WebResource *)h
 {
     ASSERT(![h defersCallbacks]);
     ASSERT(![self defersCallbacks]);
-    ASSERT([self isDownload] || ![[dataSource _controller] defersCallbacks]);
+    ASSERT(![[dataSource _controller] defersCallbacks]);
+
     LOG(Loading, "URL = %@", [dataSource _URL]);
         
     // Calls in this method will most likely result in a call to release, so we must retain.
     [self retain];
 
-    WebError *downloadError = nil;
-    
-    if (download) {
-        downloadError = [download finishedLoading];
-        [dataSource _setPrimaryLoadComplete:YES];
-    } else {
-        [dataSource _setResourceData:resourceData];
-        [dataSource _finishedLoading];
-        [[dataSource _controller] _mainReceivedBytesSoFar:[resourceData length]
-                                          fromDataSource:dataSource
-                                                complete:YES];
-    }
-
-    if(downloadError){
-        [super resource:h didFailLoadingWithError:downloadError];
-    } else {
-        [super resourceDidFinishLoading:h];
-    }
-
-    [download release];
-    download = nil;
+    [dataSource _setResourceData:resourceData];
+    [dataSource _finishedLoading];
+    [[dataSource _controller] _mainReceivedBytesSoFar:[resourceData length]
+                                        fromDataSource:dataSource
+                                            complete:YES];
+    [super resourceDidFinishLoading:h];
     
     [self release];
 }
@@ -363,7 +315,8 @@
 {
     ASSERT(![h defersCallbacks]);
     ASSERT(![self defersCallbacks]);
-    ASSERT([self isDownload] || ![[dataSource _controller] defersCallbacks]);
+    ASSERT(![[dataSource _controller] defersCallbacks]);
+
     LOG(Loading, "URL = %@, error = %@", [error failingURL], [error errorDescription]);
 
     // Calling receivedError will likely result in a call to release, so we must retain.
@@ -378,16 +331,16 @@
 - (void)startLoading:(WebRequest *)r
 {
     if ([[r URL] _web_shouldLoadAsEmptyDocument]) {
-	[self resource:handle willSendRequest:r];
+	[self resource:resource willSendRequest:r];
 
 	WebResponse *rsp = [[WebResponse alloc] init];
 	[rsp setURL:[r URL]];
 	[rsp setContentType:@"text/html"];
 	[rsp setContentLength:0];
-	[self resource:handle didReceiveResponse:rsp];
+	[self resource:resource didReceiveResponse:rsp];
 	[rsp release];
     } else {
-	[super startLoading:r];
+	[resource loadWithDelegate:proxy];
     }
 }
 
@@ -400,3 +353,42 @@
 
 
 @end
+
+ at implementation WebResourceDelegateProxy
+
+- (void)setDelegate:(id <WebResourceDelegate>)theDelegate
+{
+    if (delegate != theDelegate) {
+        [delegate release];
+        delegate = [theDelegate retain];
+    }
+}
+
+- (WebRequest *)resource:(WebResource *)resource willSendRequest:(WebRequest *)request
+{
+    return [delegate resource:resource willSendRequest:request];
+}
+
+-(void)resource:(WebResource *)resource didReceiveResponse:(WebResponse *)response
+{
+    [delegate resource:resource didReceiveResponse:response];
+}
+
+-(void)resource:(WebResource *)resource didReceiveData:(NSData *)data
+{
+    [delegate resource:resource didReceiveData:data];
+}
+
+-(void)resourceDidFinishLoading:(WebResource *)resource
+{
+    [delegate resourceDidFinishLoading:resource];
+    [delegate release];
+}
+
+-(void)resource:(WebResource *)resource didFailLoadingWithError:(WebError *)error
+{
+    [delegate resource:resource didFailLoadingWithError:error];
+    [delegate release];
+}
+
+ at end
diff --git a/WebKit/WebView.subproj/WebMainResourceLoader.h b/WebKit/WebView.subproj/WebMainResourceLoader.h
index 4e018f8..d5a17f4 100644
--- a/WebKit/WebView.subproj/WebMainResourceLoader.h
+++ b/WebKit/WebView.subproj/WebMainResourceLoader.h
@@ -14,19 +14,19 @@
 @class WebDownload;
 @class WebDataSource;
 @class WebResource;
+ at class WebResourceDelegateProxy;
 @class WebRequest;
 @class WebResponse;
 
 @interface WebMainResourceClient : WebBaseResourceHandleDelegate
 {
-    WebDownload *download;
     NSMutableData *resourceData;
     int _contentLength; // for logging only
     int _bytesReceived; // for logging only
+    WebResourceDelegateProxy *proxy;
 }
 
 - initWithDataSource:(WebDataSource *)dataSource;
-- (WebDownload *)download;
 - (NSData *)resourceData;
 
 @end
diff --git a/WebKit/WebView.subproj/WebMainResourceLoader.m b/WebKit/WebView.subproj/WebMainResourceLoader.m
index 2fea522..9ee3901 100644
--- a/WebKit/WebView.subproj/WebMainResourceLoader.m
+++ b/WebKit/WebView.subproj/WebMainResourceLoader.m
@@ -34,6 +34,13 @@
 
 // FIXME: More that is in common with WebSubresourceClient should move up into WebBaseResourceHandleDelegate.
 
+ at interface WebResourceDelegateProxy : NSObject <WebResourceDelegate>
+{
+    id <WebResourceDelegate> delegate;
+}
+- (void)setDelegate:(id <WebResourceDelegate>)theDelegate;
+ at end
+
 @implementation WebMainResourceClient
 
 - initWithDataSource:(WebDataSource *)ds
@@ -43,16 +50,17 @@
     if (self) {
         resourceData = [[NSMutableData alloc] init];
         [self setDataSource:ds];
+        proxy = [[WebResourceDelegateProxy alloc] init];
+        [proxy setDelegate:self];
     }
 
     return self;
 }
 
 - (void)dealloc
-{
-    ASSERT(download == nil);
-    
+{    
     [resourceData release];
+    [proxy release];
     
     [super dealloc];
 }
@@ -62,27 +70,9 @@
     return resourceData;
 }
 
-- (WebDownload *)download
-{
-    return download;
-}
-
-- (BOOL)isDownload
-{
-    return download != nil;
-}
-
 - (void)receivedError:(WebError *)error complete:(BOOL)isComplete
 {
-    if (download) {
-        ASSERT(isComplete);
-        [download cancel];
-        [download release];
-        download = nil;
-        [dataSource _setPrimaryLoadComplete:YES];
-    } else {
-        [dataSource _receivedError:error complete:isComplete];
-    }
+    [dataSource _receivedError:error complete:isComplete];
 }
 
 - (void)cancel
@@ -180,34 +170,20 @@
         break;
         
     case WebPolicySave:
-	[dataSource _setIsDownloading:YES];
-
-        NSString *path = [dataSource downloadPath];
-        if (path == nil || ![path isAbsolutePath]) {
-            NSString *directory = [dataSource _downloadDirectory];
-            if (directory != nil && [directory isAbsolutePath]) {
-                path = [directory stringByAppendingPathComponent:[r suggestedFilenameForSaving]];
-            } else {
-                id pd = [[dataSource _controller] policyDelegate];
-                
-                if ([pd respondsToSelector: @selector(savePathForResponse:andRequest:)])
-                    path = [pd savePathForResponse:r andRequest:req];
-                // FIXME: Maybe there a cleaner way handle the bad filename case?
-                if (path == nil || ![path isAbsolutePath]) {
-                    ERROR("Nil or non-absolute path returned from savePathForResponse:andRequest:.");
-                    [self stopLoadingForPolicyChange];
-                    return;
-                }
-            }
-
-	    [dataSource _setDownloadPath:path];
-	}
+        ASSERT([self downloadDelegate]);
 
-        [self interruptForPolicyChangeAndKeepLoading:YES];
+        WebDownload *download = [[WebDownload alloc] _initWithLoadingResource:resource dataSource:dataSource];
+        NSString *directory = [dataSource _downloadDirectory];
+        if (directory != nil && [directory isAbsolutePath]) {
+            // FIXME: Predetermined downloads should not be using this code path (3191052).
+            NSString *path = [directory stringByAppendingPathComponent:[r suggestedFilenameForSaving]];
+            [download _setPath:path];
+        }
+
+        [proxy setDelegate:(id <WebResourceDelegate>)download];
+        [download release];
         
-	// Hand off the dataSource to the download handler.  This will cause the remaining
-	// handle delegate callbacks to go to the controller's download delegate.
-	download = [[WebDownload alloc] initWithDataSource:dataSource];
+        [self interruptForPolicyChangeAndKeepLoading:YES];
         break;
 
     case WebPolicyOpenURL:
@@ -245,10 +221,10 @@
         ERROR("contentPolicyForMIMEType:andRequest:inFrame: returned an invalid content policy.");
     }
 
-    [super resource:handle didReceiveResponse:r];
+    [super resource:resource didReceiveResponse:r];
 
     if ([[req URL] _web_shouldLoadAsEmptyDocument]) {
-	[self resourceDidFinishLoading:handle];
+	[self resourceDidFinishLoading:resource];
     }
 }
 
@@ -277,10 +253,11 @@
     ASSERT([dataSource isDownloading] || ![[dataSource _controller] defersCallbacks]);
     [dataSource _setResponse:r];
 
-    LOG(Download, "main content type: %@", [r contentType]);
+    LOG(Loading, "main content type: %@", [r contentType]);
 
     [[dataSource _controller] setDefersCallbacks:YES];
 
+    // FIXME: Predetermined downloads should not be using this code path (3191052).
     // Figure out the content policy.
     if (![dataSource isDownloading]) {
 	[self checkContentPolicyForResponse:r andCallSelector:@selector(continueAfterContentPolicy:response:)];
@@ -297,64 +274,39 @@
     ASSERT([data length] != 0);
     ASSERT(![h defersCallbacks]);
     ASSERT(![self defersCallbacks]);
-    ASSERT([self isDownload] || ![[dataSource _controller] defersCallbacks]);
+    ASSERT(![[dataSource _controller] defersCallbacks]);
  
     LOG(Loading, "URL = %@, data = %p, length %d", [dataSource _URL], data, [data length]);
 
-    WebError *downloadError= nil;
-    
-    if (download) {
-        downloadError = [download receivedData:data];
-    } else {
-        [resourceData appendData:data];
-        [dataSource _receivedData:data];
-        [[dataSource _controller] _mainReceivedBytesSoFar:[resourceData length]
-                                          fromDataSource:dataSource
-                                                complete:NO];
-    }
-    
+    [resourceData appendData:data];
+    [dataSource _receivedData:data];
+    [[dataSource _controller] _mainReceivedBytesSoFar:[resourceData length]
+                                        fromDataSource:dataSource
+                                            complete:NO];
+
     [super resource:h didReceiveData:data];
     _bytesReceived += [data length];
-    
-    if(downloadError){
-        // Cancel download after calling didReceiveData to preserve ordering of calls.
-        [self cancelWithError:downloadError];
-    }
 
-    LOG(Download, "%d of %d", _bytesReceived, _contentLength);
+    LOG(Loading, "%d of %d", _bytesReceived, _contentLength);
 }
 
 - (void)resourceDidFinishLoading:(WebResource *)h
 {
     ASSERT(![h defersCallbacks]);
     ASSERT(![self defersCallbacks]);
-    ASSERT([self isDownload] || ![[dataSource _controller] defersCallbacks]);
+    ASSERT(![[dataSource _controller] defersCallbacks]);
+
     LOG(Loading, "URL = %@", [dataSource _URL]);
         
     // Calls in this method will most likely result in a call to release, so we must retain.
     [self retain];
 
-    WebError *downloadError = nil;
-    
-    if (download) {
-        downloadError = [download finishedLoading];
-        [dataSource _setPrimaryLoadComplete:YES];
-    } else {
-        [dataSource _setResourceData:resourceData];
-        [dataSource _finishedLoading];
-        [[dataSource _controller] _mainReceivedBytesSoFar:[resourceData length]
-                                          fromDataSource:dataSource
-                                                complete:YES];
-    }
-
-    if(downloadError){
-        [super resource:h didFailLoadingWithError:downloadError];
-    } else {
-        [super resourceDidFinishLoading:h];
-    }
-
-    [download release];
-    download = nil;
+    [dataSource _setResourceData:resourceData];
+    [dataSource _finishedLoading];
+    [[dataSource _controller] _mainReceivedBytesSoFar:[resourceData length]
+                                        fromDataSource:dataSource
+                                            complete:YES];
+    [super resourceDidFinishLoading:h];
     
     [self release];
 }
@@ -363,7 +315,8 @@
 {
     ASSERT(![h defersCallbacks]);
     ASSERT(![self defersCallbacks]);
-    ASSERT([self isDownload] || ![[dataSource _controller] defersCallbacks]);
+    ASSERT(![[dataSource _controller] defersCallbacks]);
+
     LOG(Loading, "URL = %@, error = %@", [error failingURL], [error errorDescription]);
 
     // Calling receivedError will likely result in a call to release, so we must retain.
@@ -378,16 +331,16 @@
 - (void)startLoading:(WebRequest *)r
 {
     if ([[r URL] _web_shouldLoadAsEmptyDocument]) {
-	[self resource:handle willSendRequest:r];
+	[self resource:resource willSendRequest:r];
 
 	WebResponse *rsp = [[WebResponse alloc] init];
 	[rsp setURL:[r URL]];
 	[rsp setContentType:@"text/html"];
 	[rsp setContentLength:0];
-	[self resource:handle didReceiveResponse:rsp];
+	[self resource:resource didReceiveResponse:rsp];
 	[rsp release];
     } else {
-	[super startLoading:r];
+	[resource loadWithDelegate:proxy];
     }
 }
 
@@ -400,3 +353,42 @@
 
 
 @end
+
+ at implementation WebResourceDelegateProxy
+
+- (void)setDelegate:(id <WebResourceDelegate>)theDelegate
+{
+    if (delegate != theDelegate) {
+        [delegate release];
+        delegate = [theDelegate retain];
+    }
+}
+
+- (WebRequest *)resource:(WebResource *)resource willSendRequest:(WebRequest *)request
+{
+    return [delegate resource:resource willSendRequest:request];
+}
+
+-(void)resource:(WebResource *)resource didReceiveResponse:(WebResponse *)response
+{
+    [delegate resource:resource didReceiveResponse:response];
+}
+
+-(void)resource:(WebResource *)resource didReceiveData:(NSData *)data
+{
+    [delegate resource:resource didReceiveData:data];
+}
+
+-(void)resourceDidFinishLoading:(WebResource *)resource
+{
+    [delegate resourceDidFinishLoading:resource];
+    [delegate release];
+}
+
+-(void)resource:(WebResource *)resource didFailLoadingWithError:(WebError *)error
+{
+    [delegate resource:resource didFailLoadingWithError:error];
+    [delegate release];
+}
+
+ at end
diff --git a/WebKit/WebView.subproj/WebPolicyDelegate.h b/WebKit/WebView.subproj/WebPolicyDelegate.h
index 46fdad5..de07d81 100644
--- a/WebKit/WebView.subproj/WebPolicyDelegate.h
+++ b/WebKit/WebView.subproj/WebPolicyDelegate.h
@@ -117,18 +117,6 @@ typedef enum {
                                  andRequest:(WebRequest *)request
                                     inFrame:(WebFrame *)frame;
 
-
-/*!
-    @method saveFilenameForResponse:andRequest:
-    @discussion Returns the filename to use for a load that's being saved.
-    @param response The response for the partially loaded content.
-    @param request A WebResourceRequest for the partially loaded content.
-    @result The filename to use to save a loaded resource.
-*/
-- (NSString *)savePathForResponse:(WebResponse *)response
-                       andRequest:(WebRequest *)request;
-
-
 /*!
     @method unableToImplementPolicy:error:forURL:inFrame:
     @discussion Called when a WebPolicy could not be implemented. It is up to the client to display appropriate feedback.
diff --git a/WebKit/WebView.subproj/WebView.h b/WebKit/WebView.subproj/WebView.h
index 0ce09ae..f325c6f 100644
--- a/WebKit/WebView.subproj/WebView.h
+++ b/WebKit/WebView.subproj/WebView.h
@@ -146,15 +146,15 @@ extern NSString *WebElementLinkLabelKey;	// NSString of the text within the anch
 
 /*!
     @method setDownloadDelegate:
-    @abstract Set the controller's WebResourceLoadDelegate download delegate.
-    @param delegate The WebResourceLoadDelegate to set as the download delegate.
+    @abstract Set the controller's WebDownloadDelegate.
+    @param delegate The WebDownloadDelegate to set as the download delegate.
 */    
 - (void)setDownloadDelegate: (id)delegate;
 
 /*!
     @method downloadDelegate
-    @abstract Return the controller's WebResourceLoadDelegate download delegate.
-    @result The controller's WebResourceLoadDelegate download delegate.
+    @abstract Return the controller's WebDownloadDelegate.
+    @result The controller's WebDownloadDelegate.
 */    
 - (id)downloadDelegate;
 
diff --git a/WebKit/WebView.subproj/WebView.m b/WebKit/WebView.subproj/WebView.m
index 827b5dc..362bfaf 100644
--- a/WebKit/WebView.subproj/WebView.m
+++ b/WebKit/WebView.subproj/WebView.m
@@ -167,13 +167,13 @@ NSString *WebElementLinkTitleKey = 		@"WebElementLinkTitle";
 
 - (void)setDownloadDelegate: delegate
 {
-    _private->downloadProgressDelegate = delegate;
+    _private->downloadDelegate = delegate;
 }
 
 
 - downloadDelegate
 {
-    return _private->downloadProgressDelegate;
+    return _private->downloadDelegate;
 }
 
 - (void)setContextMenuDelegate: delegate
diff --git a/WebKit/WebView.subproj/WebViewPrivate.h b/WebKit/WebView.subproj/WebViewPrivate.h
index 19bd75f..c2d3cf5 100644
--- a/WebKit/WebView.subproj/WebViewPrivate.h
+++ b/WebKit/WebView.subproj/WebViewPrivate.h
@@ -24,7 +24,7 @@ enum { NumUserAgentStringTypes = WinIE + 1 };
     
     id windowContext;
     id resourceProgressDelegate;
-    id downloadProgressDelegate;
+    id downloadDelegate;
     id contextMenuDelegate;
     id policyDelegate;
     id locationChangeDelegate;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list