[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:23:53 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit 2368ce6d715497cf12138e72aa952f23ff3e0da5
Author: cblu <cblu at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Feb 6 23:08:52 2003 +0000

    	Fixed: 3125067 - Investigate performance implications of writing download file data
    
            Reviewed by trey, rjw, darin.
    
            * Downloads.subproj/WebDownloadHandler.h:
            * Downloads.subproj/WebDownloadHandler.m:
            (-[WebDownloadHandler closeFileAndDelete:]): close the file asynchronously
            (-[WebDownloadHandler closeFile]): call closeFileAndDelete:NO
            (-[WebDownloadHandler cleanUpAfterFailure]): call closeFileAndDelete:YES
            (-[WebDownloadHandler writeDataForkData:resourceForkData:]): call writeForkData:isDataFork:
            (-[WebDownloadHandler path]): new
            (-[WebDownloadHandler writeForkData:isDataFork:]): writes file asynchronously
            (-[WebDownloadHandler errorWithCode:]): moved
            (-[WebDownloadHandler cancelWithError:]): new, stops load with error
            (-[WebDownloadHandler dataForkReferenceNumber]): new
            (-[WebDownloadHandler setDataForkReferenceNumber:]): new
            (-[WebDownloadHandler resourceForkReferenceNumber]): new
            (-[WebDownloadHandler setResourceForkReferenceNumber:]): new
            (WriteCompletionCallback): new
            (CloseCompletionCallback): new, removes file if necessary
            (DeleteCompletionCallback): new,
            * WebView.subproj/WebDataSourcePrivate.h:
            * WebView.subproj/WebDataSourcePrivate.m:
            (-[WebDataSource _stopLoadingWithError:]): new
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@3586 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog
index 8d98c8b..33002c2 100644
--- a/WebKit/ChangeLog
+++ b/WebKit/ChangeLog
@@ -1,3 +1,30 @@
+2003-02-06  Chris Blumenberg  <cblu at apple.com>
+
+	Fixed: 3125067 - Investigate performance implications of writing download file data
+	
+        Reviewed by trey, rjw, darin.
+
+        * Downloads.subproj/WebDownloadHandler.h:
+        * Downloads.subproj/WebDownloadHandler.m:
+        (-[WebDownloadHandler closeFileAndDelete:]): close the file asynchronously
+        (-[WebDownloadHandler closeFile]): call closeFileAndDelete:NO
+        (-[WebDownloadHandler cleanUpAfterFailure]): call closeFileAndDelete:YES
+        (-[WebDownloadHandler writeDataForkData:resourceForkData:]): call writeForkData:isDataFork:
+        (-[WebDownloadHandler path]): new
+        (-[WebDownloadHandler writeForkData:isDataFork:]): writes file asynchronously
+        (-[WebDownloadHandler errorWithCode:]): moved
+        (-[WebDownloadHandler cancelWithError:]): new, stops load with error
+        (-[WebDownloadHandler dataForkReferenceNumber]): new 
+        (-[WebDownloadHandler setDataForkReferenceNumber:]): new
+        (-[WebDownloadHandler resourceForkReferenceNumber]): new
+        (-[WebDownloadHandler setResourceForkReferenceNumber:]): new
+        (WriteCompletionCallback): new
+        (CloseCompletionCallback): new, removes file if necessary
+        (DeleteCompletionCallback): new,
+        * WebView.subproj/WebDataSourcePrivate.h:
+        * WebView.subproj/WebDataSourcePrivate.m:
+        (-[WebDataSource _stopLoadingWithError:]): new
+
 2003-02-06  Trey Matteson  <trey at apple.com>
 
 	3137647 - ad frames get their own history entries at channels.netscape.com	
diff --git a/WebKit/Downloads.subproj/WebDownload.h b/WebKit/Downloads.subproj/WebDownload.h
index 634b809..184da84 100644
--- a/WebKit/Downloads.subproj/WebDownload.h
+++ b/WebKit/Downloads.subproj/WebDownload.h
@@ -25,6 +25,13 @@
     
     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 areWritesCancelled;
 }
 
 - initWithDataSource:(WebDataSource *)dSource;
diff --git a/WebKit/Downloads.subproj/WebDownload.m b/WebKit/Downloads.subproj/WebDownload.m
index 60be428..9f700cd 100644
--- a/WebKit/Downloads.subproj/WebDownload.m
+++ b/WebKit/Downloads.subproj/WebDownload.m
@@ -23,6 +23,37 @@
 #import <WebFoundation/WebResourceRequest.h>
 #import <WebFoundation/WebResourceResponse.h>
 
+typedef struct WebFSForkIOParam
+{
+    FSForkIOParam paramBlock;
+    WebDownloadHandler *downloadHandler;
+    BOOL deleteFile;
+    NSData *data;
+} WebFSForkIOParam;
+
+typedef struct WebFSRefParam
+{
+    FSRefParam paramBlock;
+    WebDownloadHandler *downloadHandler;
+} WebFSRefParam;
+
+static void WriteCompletionCallback(ParmBlkPtr paramBlock);
+static void CloseCompletionCallback(ParmBlkPtr paramBlock);
+static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
+
+ at interface WebDownloadHandler (WebPrivate)
+- (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;
+ at end
+
 @implementation WebDownloadHandler
 
 - initWithDataSource:(WebDataSource *)dSource
@@ -50,11 +81,6 @@
     [super dealloc];
 }
 
-- (WebError *)errorWithCode:(int)code
-{
-    return [WebError errorWithCode:code inDomain:WebErrorDomainWebKit failingURL:[[dataSource URL] absoluteString]];
-}
-
 - (void)decodeHeaderData:(NSData *)headerData
             dataForkData:(NSData **)dataForkData
         resourceForkData:(NSData **)resourceForkData
@@ -120,42 +146,33 @@
     return YES;
 }
 
-- (void)closeFile
+- (void)closeFork:(SInt16)forkRefNum deleteFile:(BOOL)deleteFile
 {
-    if (dataForkRefNum) {
-        FSCloseFork(dataForkRefNum);
-        dataForkRefNum = 0;
-    }
-    if (resourceForkRefNum) {
-        FSCloseFork(resourceForkRefNum);
-        resourceForkRefNum = 0;
+    if (forkRefNum) {
+        WebFSForkIOParam *block = malloc(sizeof(WebFSForkIOParam));
+        block->paramBlock.ioCompletion = CloseCompletionCallback;
+        block->paramBlock.forkRefNum = forkRefNum;
+        block->paramBlock.ref = fileRefPtr;
+        block->downloadHandler = [self retain];
+        block->deleteFile = deleteFile;
+        PBCloseForkAsync(&block->paramBlock);
     }
 }
 
+- (void)closeFileAndDelete:(BOOL)deleteFile
+{
+    [self closeFork:dataForkRefNum deleteFile:deleteFile];
+    [self closeFork:resourceForkRefNum deleteFile:deleteFile];
+}
+
+- (void)closeFile
+{
+    [self closeFileAndDelete:NO];
+}
+
 - (void)cleanUpAfterFailure
 {
-    // VERY IMPORTANT TEST.  Only cleanup if we have opened a file, since the downloadPath
-    // might be an existing file that we haven't discovered that we conflict with.  This can
-    // happen if we're cleaning up after we received the first response, but before the first
-    // data was processed.
-    if (fileRefPtr) {
-        NSString *path = [dataSource downloadPath];
-
-        [self closeFile];
-
-        NSFileManager *fileMgr = [NSFileManager defaultManager];
-        BOOL isDirectory;
-        BOOL fileExists = [fileMgr fileExistsAtPath:path isDirectory:&isDirectory];
-        if (fileExists && !isDirectory) {
-            [fileMgr _web_removeFileOnlyAtPath:path];
-            [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:path];
-        } else if (!fileExists) {
-            ERROR("Download file disappeared in the middle of download");
-        } else {
-            // Note we currently don't support downloading directories, so we know this is wrong
-            ERROR("Download file is a directory - will not be removed");
-        }
-    }
+    [self closeFileAndDelete:YES];
 }
 
 - (WebError *)createFileIfNecessary
@@ -224,39 +241,6 @@
     return nil;
 }
 
-- (BOOL)writeData:(NSData *)data toFork:(SInt16 *)forkRefNum
-{
-    OSErr result;
-    
-    if (*forkRefNum == 0) {
-        HFSUniStr255 forkName;
-        if (forkRefNum == &dataForkRefNum) {
-            result = FSGetDataForkName(&forkName);
-        } else {
-            result = FSGetResourceForkName(&forkName);
-        }
-                
-        if (result != noErr) {
-            ERROR("Couldn't get fork name of download file.");
-            return NO;
-        }
-
-        result = FSOpenFork(fileRefPtr, forkName.length, forkName.unicode, fsWrPerm, forkRefNum);
-        if (result != noErr) {
-            ERROR("Couldn't open fork of download file.");
-            return NO;
-        }
-    }
-
-    result = FSWriteFork(*forkRefNum, fsAtMark, 0, [data length], [data bytes], NULL);
-    if (result != noErr) {
-        ERROR("Couldn't write to fork of download file.");
-        return NO;
-    }
-
-    return YES;
-}
-
 - (WebError *)writeDataForkData:(NSData *)dataForkData resourceForkData:(NSData *)resourceForkData
 {
     WebError *error = [self createFileIfNecessary];
@@ -267,15 +251,14 @@
     BOOL didWrite = YES;
     
     if ([dataForkData length]) {
-        didWrite = [self writeData:dataForkData toFork:&dataForkRefNum];
+        didWrite = [self writeForkData:dataForkData isDataFork:YES];
     }
 
     if (didWrite && [resourceForkData length]) {
-        didWrite = [self writeData:resourceForkData toFork:&resourceForkRefNum];
+        didWrite = [self writeForkData:resourceForkData isDataFork:NO];
     }
 
     if (!didWrite) {
-        ERROR("Writing to download file failed.");
         [self cleanUpAfterFailure];
         return [self errorWithCode:WebKitErrorCannotWriteToFile];
     }
@@ -369,8 +352,6 @@
 
     [self closeFile];
 
-    [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:[dataSource downloadPath]];
-
     LOG(Download, "Download complete. Saved to: %@", [dataSource downloadPath]);
 
     return nil;
@@ -378,7 +359,176 @@
 
 - (void)cancel
 {
+    isCancelled = YES;
     [self cleanUpAfterFailure];
 }
 
 @end
+
+
+ at implementation WebDownloadHandler (WebPrivate)
+
+- (NSString *)path
+{
+    return [dataSource downloadPath];
+}
+
+- (BOOL)writeForkData:(NSData *)data isDataFork:(BOOL)isDataFork
+{
+    ASSERT(!isCancelled);
+    
+    OSErr result;
+    SInt16 *forkRefNum = isDataFork ? &dataForkRefNum : &resourceForkRefNum;
+    
+    if (*forkRefNum == 0) {
+        HFSUniStr255 forkName;
+        if (isDataFork) {
+            result = FSGetDataForkName(&forkName);
+        } else {
+            result = FSGetResourceForkName(&forkName);
+        }
+
+        if (result != noErr) {
+            ERROR("Couldn't get fork name of download file.");
+            return NO;
+        }
+
+        result = FSOpenFork(fileRefPtr, forkName.length, forkName.unicode, fsWrPerm, forkRefNum);
+        if (result != noErr) {
+            ERROR("Couldn't open fork of download file.");
+            return NO;
+        }
+    }
+    
+    WebFSForkIOParam *block = malloc(sizeof(WebFSForkIOParam));
+    block->paramBlock.ioCompletion = WriteCompletionCallback;
+    block->paramBlock.forkRefNum = *forkRefNum;
+    block->paramBlock.positionMode = fsAtMark;
+    block->paramBlock.positionOffset = 0;
+    block->paramBlock.requestCount = [data length];
+    block->paramBlock.buffer = (Ptr)[data bytes];
+    block->downloadHandler = [self retain];
+    block->data = [data copy];
+    PBWriteForkAsync(&block->paramBlock);
+
+    return YES;
+}
+
+- (WebError *)errorWithCode:(int)code
+{
+    return [WebError errorWithCode:code inDomain:WebErrorDomainWebKit failingURL:[[dataSource URL] absoluteString]];
+}
+
+- (void)cancelWithError:(WebError *)error
+{
+    [dataSource _stopLoadingWithError:error];
+}
+
+- (SInt16)dataForkReferenceNumber
+{
+    return dataForkRefNum;
+}
+
+- (void)setDataForkReferenceNumber:(SInt16)forkRefNum
+{
+    dataForkRefNum = forkRefNum;
+}
+
+- (SInt16)resourceForkReferenceNumber
+{
+    return resourceForkRefNum;
+}
+
+- (void)setResourceForkReferenceNumber:(SInt16)forkRefNum
+{
+    resourceForkRefNum = forkRefNum;
+}
+
+- (BOOL)areWritesCancelled
+{
+    return areWritesCancelled;
+}
+
+- (void)setWritesCancelled:(BOOL)cancelled
+{
+    areWritesCancelled = cancelled;
+}
+
+ at end
+
+static void WriteCompletionCallback(ParmBlkPtr paramBlock)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    WebFSForkIOParam *block = (WebFSForkIOParam *)paramBlock;
+    WebDownloadHandler *downloadHandler = block->downloadHandler;
+    
+    if (block->paramBlock.ioResult != noErr && ![downloadHandler areWritesCancelled]) {
+        ERROR("Writing to fork of download file failed with error: %d", block->paramBlock.ioResult);
+        [downloadHandler setWritesCancelled:YES];
+        [downloadHandler performSelectorOnMainThread:@selector(cancelWithError:)
+                                          withObject:[downloadHandler errorWithCode:WebKitErrorCannotWriteToFile]
+                                       waitUntilDone:NO];
+    }
+
+    [downloadHandler release];
+    [block->data release];
+    [pool release];
+    free(block);
+}
+
+static void CloseCompletionCallback(ParmBlkPtr paramBlock)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    WebFSForkIOParam *block = (WebFSForkIOParam *)paramBlock;
+    WebDownloadHandler *downloadHandler = block->downloadHandler;
+    
+    if (block->paramBlock.ioResult != noErr) {
+        ERROR("Closing fork of download file failed with error: %d", block->paramBlock.ioResult);
+        // FIXME: Need to report close errors.
+    }
+
+    if (block->paramBlock.forkRefNum == [downloadHandler dataForkReferenceNumber]) {
+        [downloadHandler setDataForkReferenceNumber:0];
+    } else {
+        [downloadHandler setResourceForkReferenceNumber:0];
+    }
+
+    // Check if both the data fork and resource fork are now closed.
+    if ([downloadHandler dataForkReferenceNumber] == 0 && [downloadHandler resourceForkReferenceNumber] == 0) {
+        if (block->deleteFile && block->paramBlock.ref) {
+            WebFSRefParam *deleteBlock = malloc(sizeof(WebFSRefParam));
+            deleteBlock->paramBlock.ioCompletion = DeleteCompletionCallback;
+            deleteBlock->paramBlock.ref = block->paramBlock.ref;
+            deleteBlock->downloadHandler = [downloadHandler retain];                
+            PBDeleteObjectAsync(&deleteBlock->paramBlock);
+        } else {
+            [[NSWorkspace sharedWorkspace] performSelectorOnMainThread:@selector(_web_noteFileChangedAtPath:)
+                                                            withObject:[downloadHandler path]
+                                                         waitUntilDone:NO];
+        }
+    }
+    
+    [downloadHandler release];
+    [pool release];
+    free(block);
+}
+
+static void DeleteCompletionCallback(ParmBlkPtr paramBlock)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    WebFSRefParam *block = (WebFSRefParam *)paramBlock;
+    WebDownloadHandler *downloadHandler = block->downloadHandler;
+    
+    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:[downloadHandler path]
+                                                     waitUntilDone:NO];
+    }
+    
+    [downloadHandler release];
+    [pool release];
+    free(block);
+}
+
diff --git a/WebKit/Downloads.subproj/WebDownloadHandler.h b/WebKit/Downloads.subproj/WebDownloadHandler.h
index 634b809..184da84 100644
--- a/WebKit/Downloads.subproj/WebDownloadHandler.h
+++ b/WebKit/Downloads.subproj/WebDownloadHandler.h
@@ -25,6 +25,13 @@
     
     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 areWritesCancelled;
 }
 
 - initWithDataSource:(WebDataSource *)dSource;
diff --git a/WebKit/Downloads.subproj/WebDownloadHandler.m b/WebKit/Downloads.subproj/WebDownloadHandler.m
index 60be428..9f700cd 100644
--- a/WebKit/Downloads.subproj/WebDownloadHandler.m
+++ b/WebKit/Downloads.subproj/WebDownloadHandler.m
@@ -23,6 +23,37 @@
 #import <WebFoundation/WebResourceRequest.h>
 #import <WebFoundation/WebResourceResponse.h>
 
+typedef struct WebFSForkIOParam
+{
+    FSForkIOParam paramBlock;
+    WebDownloadHandler *downloadHandler;
+    BOOL deleteFile;
+    NSData *data;
+} WebFSForkIOParam;
+
+typedef struct WebFSRefParam
+{
+    FSRefParam paramBlock;
+    WebDownloadHandler *downloadHandler;
+} WebFSRefParam;
+
+static void WriteCompletionCallback(ParmBlkPtr paramBlock);
+static void CloseCompletionCallback(ParmBlkPtr paramBlock);
+static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
+
+ at interface WebDownloadHandler (WebPrivate)
+- (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;
+ at end
+
 @implementation WebDownloadHandler
 
 - initWithDataSource:(WebDataSource *)dSource
@@ -50,11 +81,6 @@
     [super dealloc];
 }
 
-- (WebError *)errorWithCode:(int)code
-{
-    return [WebError errorWithCode:code inDomain:WebErrorDomainWebKit failingURL:[[dataSource URL] absoluteString]];
-}
-
 - (void)decodeHeaderData:(NSData *)headerData
             dataForkData:(NSData **)dataForkData
         resourceForkData:(NSData **)resourceForkData
@@ -120,42 +146,33 @@
     return YES;
 }
 
-- (void)closeFile
+- (void)closeFork:(SInt16)forkRefNum deleteFile:(BOOL)deleteFile
 {
-    if (dataForkRefNum) {
-        FSCloseFork(dataForkRefNum);
-        dataForkRefNum = 0;
-    }
-    if (resourceForkRefNum) {
-        FSCloseFork(resourceForkRefNum);
-        resourceForkRefNum = 0;
+    if (forkRefNum) {
+        WebFSForkIOParam *block = malloc(sizeof(WebFSForkIOParam));
+        block->paramBlock.ioCompletion = CloseCompletionCallback;
+        block->paramBlock.forkRefNum = forkRefNum;
+        block->paramBlock.ref = fileRefPtr;
+        block->downloadHandler = [self retain];
+        block->deleteFile = deleteFile;
+        PBCloseForkAsync(&block->paramBlock);
     }
 }
 
+- (void)closeFileAndDelete:(BOOL)deleteFile
+{
+    [self closeFork:dataForkRefNum deleteFile:deleteFile];
+    [self closeFork:resourceForkRefNum deleteFile:deleteFile];
+}
+
+- (void)closeFile
+{
+    [self closeFileAndDelete:NO];
+}
+
 - (void)cleanUpAfterFailure
 {
-    // VERY IMPORTANT TEST.  Only cleanup if we have opened a file, since the downloadPath
-    // might be an existing file that we haven't discovered that we conflict with.  This can
-    // happen if we're cleaning up after we received the first response, but before the first
-    // data was processed.
-    if (fileRefPtr) {
-        NSString *path = [dataSource downloadPath];
-
-        [self closeFile];
-
-        NSFileManager *fileMgr = [NSFileManager defaultManager];
-        BOOL isDirectory;
-        BOOL fileExists = [fileMgr fileExistsAtPath:path isDirectory:&isDirectory];
-        if (fileExists && !isDirectory) {
-            [fileMgr _web_removeFileOnlyAtPath:path];
-            [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:path];
-        } else if (!fileExists) {
-            ERROR("Download file disappeared in the middle of download");
-        } else {
-            // Note we currently don't support downloading directories, so we know this is wrong
-            ERROR("Download file is a directory - will not be removed");
-        }
-    }
+    [self closeFileAndDelete:YES];
 }
 
 - (WebError *)createFileIfNecessary
@@ -224,39 +241,6 @@
     return nil;
 }
 
-- (BOOL)writeData:(NSData *)data toFork:(SInt16 *)forkRefNum
-{
-    OSErr result;
-    
-    if (*forkRefNum == 0) {
-        HFSUniStr255 forkName;
-        if (forkRefNum == &dataForkRefNum) {
-            result = FSGetDataForkName(&forkName);
-        } else {
-            result = FSGetResourceForkName(&forkName);
-        }
-                
-        if (result != noErr) {
-            ERROR("Couldn't get fork name of download file.");
-            return NO;
-        }
-
-        result = FSOpenFork(fileRefPtr, forkName.length, forkName.unicode, fsWrPerm, forkRefNum);
-        if (result != noErr) {
-            ERROR("Couldn't open fork of download file.");
-            return NO;
-        }
-    }
-
-    result = FSWriteFork(*forkRefNum, fsAtMark, 0, [data length], [data bytes], NULL);
-    if (result != noErr) {
-        ERROR("Couldn't write to fork of download file.");
-        return NO;
-    }
-
-    return YES;
-}
-
 - (WebError *)writeDataForkData:(NSData *)dataForkData resourceForkData:(NSData *)resourceForkData
 {
     WebError *error = [self createFileIfNecessary];
@@ -267,15 +251,14 @@
     BOOL didWrite = YES;
     
     if ([dataForkData length]) {
-        didWrite = [self writeData:dataForkData toFork:&dataForkRefNum];
+        didWrite = [self writeForkData:dataForkData isDataFork:YES];
     }
 
     if (didWrite && [resourceForkData length]) {
-        didWrite = [self writeData:resourceForkData toFork:&resourceForkRefNum];
+        didWrite = [self writeForkData:resourceForkData isDataFork:NO];
     }
 
     if (!didWrite) {
-        ERROR("Writing to download file failed.");
         [self cleanUpAfterFailure];
         return [self errorWithCode:WebKitErrorCannotWriteToFile];
     }
@@ -369,8 +352,6 @@
 
     [self closeFile];
 
-    [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:[dataSource downloadPath]];
-
     LOG(Download, "Download complete. Saved to: %@", [dataSource downloadPath]);
 
     return nil;
@@ -378,7 +359,176 @@
 
 - (void)cancel
 {
+    isCancelled = YES;
     [self cleanUpAfterFailure];
 }
 
 @end
+
+
+ at implementation WebDownloadHandler (WebPrivate)
+
+- (NSString *)path
+{
+    return [dataSource downloadPath];
+}
+
+- (BOOL)writeForkData:(NSData *)data isDataFork:(BOOL)isDataFork
+{
+    ASSERT(!isCancelled);
+    
+    OSErr result;
+    SInt16 *forkRefNum = isDataFork ? &dataForkRefNum : &resourceForkRefNum;
+    
+    if (*forkRefNum == 0) {
+        HFSUniStr255 forkName;
+        if (isDataFork) {
+            result = FSGetDataForkName(&forkName);
+        } else {
+            result = FSGetResourceForkName(&forkName);
+        }
+
+        if (result != noErr) {
+            ERROR("Couldn't get fork name of download file.");
+            return NO;
+        }
+
+        result = FSOpenFork(fileRefPtr, forkName.length, forkName.unicode, fsWrPerm, forkRefNum);
+        if (result != noErr) {
+            ERROR("Couldn't open fork of download file.");
+            return NO;
+        }
+    }
+    
+    WebFSForkIOParam *block = malloc(sizeof(WebFSForkIOParam));
+    block->paramBlock.ioCompletion = WriteCompletionCallback;
+    block->paramBlock.forkRefNum = *forkRefNum;
+    block->paramBlock.positionMode = fsAtMark;
+    block->paramBlock.positionOffset = 0;
+    block->paramBlock.requestCount = [data length];
+    block->paramBlock.buffer = (Ptr)[data bytes];
+    block->downloadHandler = [self retain];
+    block->data = [data copy];
+    PBWriteForkAsync(&block->paramBlock);
+
+    return YES;
+}
+
+- (WebError *)errorWithCode:(int)code
+{
+    return [WebError errorWithCode:code inDomain:WebErrorDomainWebKit failingURL:[[dataSource URL] absoluteString]];
+}
+
+- (void)cancelWithError:(WebError *)error
+{
+    [dataSource _stopLoadingWithError:error];
+}
+
+- (SInt16)dataForkReferenceNumber
+{
+    return dataForkRefNum;
+}
+
+- (void)setDataForkReferenceNumber:(SInt16)forkRefNum
+{
+    dataForkRefNum = forkRefNum;
+}
+
+- (SInt16)resourceForkReferenceNumber
+{
+    return resourceForkRefNum;
+}
+
+- (void)setResourceForkReferenceNumber:(SInt16)forkRefNum
+{
+    resourceForkRefNum = forkRefNum;
+}
+
+- (BOOL)areWritesCancelled
+{
+    return areWritesCancelled;
+}
+
+- (void)setWritesCancelled:(BOOL)cancelled
+{
+    areWritesCancelled = cancelled;
+}
+
+ at end
+
+static void WriteCompletionCallback(ParmBlkPtr paramBlock)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    WebFSForkIOParam *block = (WebFSForkIOParam *)paramBlock;
+    WebDownloadHandler *downloadHandler = block->downloadHandler;
+    
+    if (block->paramBlock.ioResult != noErr && ![downloadHandler areWritesCancelled]) {
+        ERROR("Writing to fork of download file failed with error: %d", block->paramBlock.ioResult);
+        [downloadHandler setWritesCancelled:YES];
+        [downloadHandler performSelectorOnMainThread:@selector(cancelWithError:)
+                                          withObject:[downloadHandler errorWithCode:WebKitErrorCannotWriteToFile]
+                                       waitUntilDone:NO];
+    }
+
+    [downloadHandler release];
+    [block->data release];
+    [pool release];
+    free(block);
+}
+
+static void CloseCompletionCallback(ParmBlkPtr paramBlock)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    WebFSForkIOParam *block = (WebFSForkIOParam *)paramBlock;
+    WebDownloadHandler *downloadHandler = block->downloadHandler;
+    
+    if (block->paramBlock.ioResult != noErr) {
+        ERROR("Closing fork of download file failed with error: %d", block->paramBlock.ioResult);
+        // FIXME: Need to report close errors.
+    }
+
+    if (block->paramBlock.forkRefNum == [downloadHandler dataForkReferenceNumber]) {
+        [downloadHandler setDataForkReferenceNumber:0];
+    } else {
+        [downloadHandler setResourceForkReferenceNumber:0];
+    }
+
+    // Check if both the data fork and resource fork are now closed.
+    if ([downloadHandler dataForkReferenceNumber] == 0 && [downloadHandler resourceForkReferenceNumber] == 0) {
+        if (block->deleteFile && block->paramBlock.ref) {
+            WebFSRefParam *deleteBlock = malloc(sizeof(WebFSRefParam));
+            deleteBlock->paramBlock.ioCompletion = DeleteCompletionCallback;
+            deleteBlock->paramBlock.ref = block->paramBlock.ref;
+            deleteBlock->downloadHandler = [downloadHandler retain];                
+            PBDeleteObjectAsync(&deleteBlock->paramBlock);
+        } else {
+            [[NSWorkspace sharedWorkspace] performSelectorOnMainThread:@selector(_web_noteFileChangedAtPath:)
+                                                            withObject:[downloadHandler path]
+                                                         waitUntilDone:NO];
+        }
+    }
+    
+    [downloadHandler release];
+    [pool release];
+    free(block);
+}
+
+static void DeleteCompletionCallback(ParmBlkPtr paramBlock)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    WebFSRefParam *block = (WebFSRefParam *)paramBlock;
+    WebDownloadHandler *downloadHandler = block->downloadHandler;
+    
+    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:[downloadHandler path]
+                                                     waitUntilDone:NO];
+    }
+    
+    [downloadHandler release];
+    [pool release];
+    free(block);
+}
+
diff --git a/WebKit/WebView.subproj/WebDataSourcePrivate.h b/WebKit/WebView.subproj/WebDataSourcePrivate.h
index ec83448..3620a9e 100644
--- a/WebKit/WebView.subproj/WebDataSourcePrivate.h
+++ b/WebKit/WebView.subproj/WebDataSourcePrivate.h
@@ -171,4 +171,6 @@
 - (void)_addResponse: (WebResourceResponse *)r;
 - (NSArray *)_responses;
 
+- (void)_stopLoadingWithError:(WebError *)error;
+
 @end
diff --git a/WebKit/WebView.subproj/WebDataSourcePrivate.m b/WebKit/WebView.subproj/WebDataSourcePrivate.m
index 6b89afe..8ff81cc 100644
--- a/WebKit/WebView.subproj/WebDataSourcePrivate.m
+++ b/WebKit/WebView.subproj/WebDataSourcePrivate.m
@@ -719,6 +719,9 @@
     return _private->responses;
 }
 
-
+- (void)_stopLoadingWithError:(WebError *)error
+{
+    [_private->mainClient cancelWithError:error];
+}
 
 @end

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list