Home | History | Annotate | Download | only in WebView
      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