[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