1 /* 2 * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #import "WebPDFRepresentation.h" 30 31 #import "WebDataSourcePrivate.h" 32 #import "WebFrame.h" 33 #import "WebJSPDFDoc.h" 34 #import "WebNSObjectExtras.h" 35 #import "WebPDFDocumentExtras.h" 36 #import "WebPDFView.h" 37 #import "WebTypesInternal.h" 38 #import <JavaScriptCore/Assertions.h> 39 #import <JavaScriptCore/JSContextRef.h> 40 #import <JavaScriptCore/JSStringRef.h> 41 #import <JavaScriptCore/JSStringRefCF.h> 42 43 @implementation WebPDFRepresentation 44 45 + (NSArray *)postScriptMIMETypes 46 { 47 return [NSArray arrayWithObjects: 48 @"application/postscript", 49 nil]; 50 } 51 52 + (NSArray *)supportedMIMETypes 53 { 54 return [[[self class] postScriptMIMETypes] arrayByAddingObjectsFromArray: 55 [NSArray arrayWithObjects: 56 @"text/pdf", 57 @"application/pdf", 58 nil]]; 59 } 60 61 + (Class)PDFDocumentClass 62 { 63 static Class PDFDocumentClass = nil; 64 if (PDFDocumentClass == nil) { 65 PDFDocumentClass = [[WebPDFView PDFKitBundle] classNamed:@"PDFDocument"]; 66 if (PDFDocumentClass == nil) { 67 LOG_ERROR("Couldn't find PDFDocument class in PDFKit.framework"); 68 } 69 } 70 return PDFDocumentClass; 71 } 72 73 - (void)setDataSource:(WebDataSource *)dataSource 74 { 75 } 76 77 - (void)receivedData:(NSData *)data withDataSource:(WebDataSource *)dataSource 78 { 79 } 80 81 - (void)receivedError:(NSError *)error withDataSource:(WebDataSource *)dataSource 82 { 83 } 84 85 - (NSData *)convertPostScriptDataSourceToPDF:(NSData *)data 86 { 87 // Convert PostScript to PDF using Quartz 2D API 88 // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_ps_convert/chapter_16_section_1.html 89 90 CGPSConverterCallbacks callbacks = { 0, 0, 0, 0, 0, 0, 0, 0 }; 91 CGPSConverterRef converter = CGPSConverterCreate(0, &callbacks, 0); 92 ASSERT(converter); 93 94 CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data); 95 ASSERT(provider); 96 97 CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); 98 ASSERT(result); 99 100 CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData(result); 101 ASSERT(consumer); 102 103 // Error handled by detecting zero-length 'result' in caller 104 CGPSConverterConvert(converter, provider, consumer, 0); 105 106 CFRelease(converter); 107 CFRelease(provider); 108 CFRelease(consumer); 109 110 return WebCFAutorelease(result); 111 } 112 113 - (void)finishedLoadingWithDataSource:(WebDataSource *)dataSource 114 { 115 NSData *data = [dataSource data]; 116 117 NSArray *postScriptMIMETypes = [[self class] postScriptMIMETypes]; 118 NSString *mimeType = [dataSource _responseMIMEType]; 119 if ([postScriptMIMETypes containsObject:mimeType]) { 120 data = [self convertPostScriptDataSourceToPDF:data]; 121 if ([data length] == 0) 122 return; 123 } 124 125 WebPDFView *view = (WebPDFView *)[[[dataSource webFrame] frameView] documentView]; 126 PDFDocument *doc = [[[[self class] PDFDocumentClass] alloc] initWithData:data]; 127 [view setPDFDocument:doc]; 128 129 NSArray *scripts = allScriptsInPDFDocument(doc); 130 [doc release]; 131 doc = nil; 132 133 NSUInteger scriptCount = [scripts count]; 134 if (!scriptCount) 135 return; 136 137 JSGlobalContextRef ctx = JSGlobalContextCreate(0); 138 JSObjectRef jsPDFDoc = makeJSPDFDoc(ctx, dataSource); 139 140 for (NSUInteger i = 0; i < scriptCount; ++i) { 141 JSStringRef script = JSStringCreateWithCFString((CFStringRef)[scripts objectAtIndex:i]); 142 JSEvaluateScript(ctx, script, jsPDFDoc, 0, 0, 0); 143 JSStringRelease(script); 144 } 145 146 JSGlobalContextRelease(ctx); 147 } 148 149 - (BOOL)canProvideDocumentSource 150 { 151 return NO; 152 } 153 154 155 - (NSString *)documentSource 156 { 157 return nil; 158 } 159 160 161 - (NSString *)title 162 { 163 return nil; 164 } 165 166 @end 167