WebKit/mac/WebView/WebPDFDocumentExtras.mm
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2009 Apple 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  * 1. Redistributions of source code must retain the above copyright
       
     8  *    notice, this list of conditions and the following disclaimer.
       
     9  * 2. Redistributions in binary form must reproduce the above copyright
       
    10  *    notice, this list of conditions and the following disclaimer in the
       
    11  *    documentation and/or other materials provided with the distribution.
       
    12  *
       
    13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
       
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
       
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
       
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
       
    24  */
       
    25 
       
    26 #import "WebPDFDocumentExtras.h"
       
    27 
       
    28 #import "WebTypesInternal.h"
       
    29 #import <JavaScriptCore/Vector.h>
       
    30 #import <JavaScriptCore/RetainPtr.h>
       
    31 #import <PDFKit/PDFDocument.h>
       
    32 #import <objc/objc-runtime.h>
       
    33 
       
    34 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
       
    35 @interface PDFDocument (Internal)
       
    36 - (CGPDFDocumentRef)documentRef;
       
    37 @end
       
    38 #endif
       
    39 
       
    40 static void appendValuesInPDFNameSubtreeToVector(CGPDFDictionaryRef subtree, Vector<CGPDFObjectRef>& values)
       
    41 {
       
    42     CGPDFArrayRef names;
       
    43     if (CGPDFDictionaryGetArray(subtree, "Names", &names)) {
       
    44         size_t nameCount = CGPDFArrayGetCount(names) / 2;
       
    45         for (size_t i = 0; i < nameCount; ++i) {
       
    46             CGPDFObjectRef object;
       
    47             CGPDFArrayGetObject(names, 2 * i + 1, &object);
       
    48             values.append(object);
       
    49         }
       
    50         return;
       
    51     }
       
    52 
       
    53     CGPDFArrayRef kids;
       
    54     if (!CGPDFDictionaryGetArray(subtree, "Kids", &kids))
       
    55         return;
       
    56 
       
    57     size_t kidCount = CGPDFArrayGetCount(kids);
       
    58     for (size_t i = 0; i < kidCount; ++i) {
       
    59         CGPDFDictionaryRef kid;
       
    60         if (!CGPDFArrayGetDictionary(kids, i, &kid))
       
    61             continue;
       
    62         appendValuesInPDFNameSubtreeToVector(kid, values);
       
    63     }
       
    64 }
       
    65 
       
    66 static void getAllValuesInPDFNameTree(CGPDFDictionaryRef tree, Vector<CGPDFObjectRef>& allValues)
       
    67 {
       
    68     appendValuesInPDFNameSubtreeToVector(tree, allValues);
       
    69 }
       
    70 
       
    71 NSArray *allScriptsInPDFDocument(PDFDocument *document)
       
    72 {
       
    73     NSMutableArray *scripts = [NSMutableArray array];
       
    74     CGPDFDocumentRef pdfDocument = [document documentRef];
       
    75     if (!pdfDocument)
       
    76         return scripts;
       
    77 
       
    78     CGPDFDictionaryRef pdfCatalog = CGPDFDocumentGetCatalog(pdfDocument);
       
    79     if (!pdfCatalog)
       
    80         return scripts;
       
    81 
       
    82     // Get the dictionary of all document-level name trees.
       
    83     CGPDFDictionaryRef namesDictionary;
       
    84     if (!CGPDFDictionaryGetDictionary(pdfCatalog, "Names", &namesDictionary))
       
    85         return scripts;
       
    86 
       
    87     // Get the document-level "JavaScript" name tree.
       
    88     CGPDFDictionaryRef javaScriptNameTree;
       
    89     if (!CGPDFDictionaryGetDictionary(namesDictionary, "JavaScript", &javaScriptNameTree))
       
    90         return scripts;
       
    91 
       
    92     // The names are aribtrary. We are only interested in the values.
       
    93     Vector<CGPDFObjectRef> objects;
       
    94     getAllValuesInPDFNameTree(javaScriptNameTree, objects);
       
    95     size_t objectCount = objects.size();
       
    96 
       
    97     for (size_t i = 0; i < objectCount; ++i) {
       
    98         CGPDFDictionaryRef javaScriptAction;
       
    99         if (!CGPDFObjectGetValue(reinterpret_cast<CGPDFObjectRef>(objects[i]), kCGPDFObjectTypeDictionary, &javaScriptAction))
       
   100             continue;
       
   101 
       
   102         // A JavaScript action must have an action type of "JavaScript".
       
   103         const char* actionType;
       
   104         if (!CGPDFDictionaryGetName(javaScriptAction, "S", &actionType) || strcmp(actionType, "JavaScript"))
       
   105             continue;
       
   106 
       
   107         const UInt8* bytes = 0;
       
   108         CFIndex length;
       
   109         CGPDFStreamRef stream;
       
   110         CGPDFStringRef string;
       
   111         RetainPtr<CFDataRef> data;
       
   112         if (CGPDFDictionaryGetStream(javaScriptAction, "JS", &stream)) {
       
   113             CGPDFDataFormat format;
       
   114             data.adoptCF(CGPDFStreamCopyData(stream, &format));
       
   115             if (!data)
       
   116                 continue;
       
   117             bytes = CFDataGetBytePtr(data.get());
       
   118             length = CFDataGetLength(data.get());
       
   119         } else if (CGPDFDictionaryGetString(javaScriptAction, "JS", &string)) {
       
   120             bytes = CGPDFStringGetBytePtr(string);
       
   121             length = CGPDFStringGetLength(string);
       
   122         }
       
   123         if (!bytes)
       
   124             continue;
       
   125 
       
   126         NSStringEncoding encoding = (length > 1 && bytes[0] == 0xFE && bytes[1] == 0xFF) ? NSUnicodeStringEncoding : NSUTF8StringEncoding;
       
   127         NSString *script = [[NSString alloc] initWithBytes:bytes length:length encoding:encoding];
       
   128         [scripts addObject:script];
       
   129         [script release];
       
   130     }
       
   131 
       
   132     return scripts;
       
   133 }