165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch/*
265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * Copyright (C) 2010 Apple Inc. All rights reserved.
365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *
465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * Redistribution and use in source and binary forms, with or without
565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * modification, are permitted provided that the following conditions
665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * are met:
765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * 1. Redistributions of source code must retain the above copyright
865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *    notice, this list of conditions and the following disclaimer.
965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * 2. Redistributions in binary form must reproduce the above copyright
1065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *    notice, this list of conditions and the following disclaimer in the
1165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *    documentation and/or other materials provided with the distribution.
1265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *
1365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
1465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
1765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
2365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THE POSSIBILITY OF SUCH DAMAGE.
2465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch */
2565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#import "config.h"
272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#import "NetscapePluginModule.h"
2865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#import <WebCore/WebCoreNSStringExtras.h>
302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#import <wtf/HashSet.h>
3165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
3265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochusing namespace WebCore;
3365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
3465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochnamespace WebKit {
3565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
3665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic bool getPluginArchitecture(CFBundleRef bundle, cpu_type_t& pluginArchitecture)
3765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
3865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    RetainPtr<CFArrayRef> pluginArchitecturesArray(AdoptCF, CFBundleCopyExecutableArchitectures(bundle));
3965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!pluginArchitecturesArray)
4065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
4165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
4265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Turn the array into a set.
4365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    HashSet<unsigned> architectures;
4465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    for (CFIndex i = 0, numPluginArchitectures = CFArrayGetCount(pluginArchitecturesArray.get()); i < numPluginArchitectures; ++i) {
4565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        CFNumberRef number = static_cast<CFNumberRef>(CFArrayGetValueAtIndex(pluginArchitecturesArray.get(), i));
4665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
4765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        SInt32 architecture;
4865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (!CFNumberGetValue(number, kCFNumberSInt32Type, &architecture))
4965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            continue;
5065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        architectures.add(architecture);
5165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
5265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
5365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#ifdef __x86_64__
5465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // We only support 64-bit Intel plug-ins on 64-bit Intel.
5565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (architectures.contains(kCFBundleExecutableArchitectureX86_64)) {
5665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        pluginArchitecture = CPU_TYPE_X86_64;
5765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return true;
5865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
5965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
6065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // We also support 32-bit Intel plug-ins on 64-bit Intel.
6165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (architectures.contains(kCFBundleExecutableArchitectureI386)) {
6265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        pluginArchitecture = CPU_TYPE_X86;
6365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return true;
6465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
6565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#elif defined(__i386__)
6665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // We only support 32-bit Intel plug-ins on 32-bit Intel.
6765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (architectures.contains(kCFBundleExecutableArchitectureI386)) {
6865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        pluginArchitecture = CPU_TYPE_X86;
6965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return true;
7065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
7165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#elif defined(__ppc64__)
7265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // We only support 64-bit PPC plug-ins on 64-bit PPC.
7365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (architectures.contains(kCFBundleExecutableArchitecturePPC64)) {
7465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        pluginArchitecture = CPU_TYPE_POWERPC64;
7565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return true;
7665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
7765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#elif defined(__ppc__)
7865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // We only support 32-bit PPC plug-ins on 32-bit PPC.
7965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (architectures.contains(kCFBundleExecutableArchitecturePPC)) {
8065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        pluginArchitecture = CPU_TYPE_POWERPC;
8165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return true;
8265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
8365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#else
8465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#error "Unhandled architecture"
8565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#endif
8665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
8765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return false;
8865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
892bde8e466a4451c7319e3a072d118917957d6554Steve Block
902bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic RetainPtr<CFDictionaryRef> getMIMETypesFromPluginBundle(CFBundleRef bundle)
912bde8e466a4451c7319e3a072d118917957d6554Steve Block{
922bde8e466a4451c7319e3a072d118917957d6554Steve Block    CFStringRef propertyListFilename = static_cast<CFStringRef>(CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginMIMETypesFilename")));
932bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (propertyListFilename) {
942bde8e466a4451c7319e3a072d118917957d6554Steve Block        RetainPtr<CFStringRef> propertyListPath(AdoptCF, CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("%@/Library/Preferences/%@"), NSHomeDirectory(), propertyListFilename));
952bde8e466a4451c7319e3a072d118917957d6554Steve Block        RetainPtr<CFURLRef> propertyListURL(AdoptCF, CFURLCreateWithFileSystemPath(kCFAllocatorDefault, propertyListPath.get(), kCFURLPOSIXPathStyle, FALSE));
962bde8e466a4451c7319e3a072d118917957d6554Steve Block
972bde8e466a4451c7319e3a072d118917957d6554Steve Block        CFDataRef propertyListData;
982bde8e466a4451c7319e3a072d118917957d6554Steve Block        CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, propertyListURL.get(), &propertyListData, 0, 0, 0);
992bde8e466a4451c7319e3a072d118917957d6554Steve Block        RetainPtr<CFPropertyListRef> propertyList(AdoptCF, CFPropertyListCreateWithData(kCFAllocatorDefault, propertyListData, kCFPropertyListImmutable, 0, 0));
1002bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (propertyListData)
1012bde8e466a4451c7319e3a072d118917957d6554Steve Block            CFRelease(propertyListData);
1022bde8e466a4451c7319e3a072d118917957d6554Steve Block
1032bde8e466a4451c7319e3a072d118917957d6554Steve Block        // FIXME: Have the plug-in create the MIME types property list if it doesn't exist.
1042bde8e466a4451c7319e3a072d118917957d6554Steve Block        // https://bugs.webkit.org/show_bug.cgi?id=57204
1052bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!propertyList || CFGetTypeID(propertyList.get()) != CFDictionaryGetTypeID())
1062bde8e466a4451c7319e3a072d118917957d6554Steve Block            return 0;
1072bde8e466a4451c7319e3a072d118917957d6554Steve Block
1082bde8e466a4451c7319e3a072d118917957d6554Steve Block        return static_cast<CFDictionaryRef>(CFDictionaryGetValue(static_cast<CFDictionaryRef>(propertyList.get()), CFSTR("WebPluginMIMETypes")));
1092bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1102bde8e466a4451c7319e3a072d118917957d6554Steve Block
1112bde8e466a4451c7319e3a072d118917957d6554Steve Block    return static_cast<CFDictionaryRef>(CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginMIMETypes")));
1122bde8e466a4451c7319e3a072d118917957d6554Steve Block}
11365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
11465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic bool getPluginInfoFromPropertyLists(CFBundleRef bundle, PluginInfo& pluginInfo)
11565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
1162bde8e466a4451c7319e3a072d118917957d6554Steve Block    RetainPtr<CFDictionaryRef> mimeTypes = getMIMETypesFromPluginBundle(bundle);
1172bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!mimeTypes || CFGetTypeID(mimeTypes.get()) != CFDictionaryGetTypeID())
11865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
11965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
12065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Get the plug-in name.
12165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    CFStringRef pluginName = static_cast<CFStringRef>(CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginName")));
12265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (pluginName && CFGetTypeID(pluginName) == CFStringGetTypeID())
12365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        pluginInfo.name = pluginName;
12465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
12565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Get the plug-in description.
12665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    CFStringRef pluginDescription = static_cast<CFStringRef>(CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginDescription")));
12765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (pluginDescription && CFGetTypeID(pluginDescription) == CFStringGetTypeID())
12865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        pluginInfo.desc = pluginDescription;
12965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
13065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Get the MIME type mapping dictionary.
1312bde8e466a4451c7319e3a072d118917957d6554Steve Block    CFIndex numMimeTypes = CFDictionaryGetCount(mimeTypes.get());
13265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Vector<CFStringRef> mimeTypesVector(numMimeTypes);
13365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Vector<CFDictionaryRef> mimeTypeInfoVector(numMimeTypes);
1342bde8e466a4451c7319e3a072d118917957d6554Steve Block    CFDictionaryGetKeysAndValues(mimeTypes.get(), reinterpret_cast<const void**>(mimeTypesVector.data()), reinterpret_cast<const void**>(mimeTypeInfoVector.data()));
13565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
13665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    for (CFIndex i = 0; i < numMimeTypes; ++i) {
13765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        MimeClassInfo mimeClassInfo;
13865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
13965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // If this MIME type is invalid, ignore it.
14065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        CFStringRef mimeType = mimeTypesVector[i];
14165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (!mimeType || CFGetTypeID(mimeType) != CFStringGetTypeID() || CFStringGetLength(mimeType) == 0)
14265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            continue;
14365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
14465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // If this MIME type doesn't have a valid info dictionary, ignore it.
14565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        CFDictionaryRef mimeTypeInfo = mimeTypeInfoVector[i];
14665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (!mimeTypeInfo || CFGetTypeID(mimeTypeInfo) != CFDictionaryGetTypeID())
14765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            continue;
14865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
14965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Get the MIME type description.
15065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        CFStringRef mimeTypeDescription = static_cast<CFStringRef>(CFDictionaryGetValue(mimeTypeInfo, CFSTR("WebPluginTypeDescription")));
15165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (mimeTypeDescription && CFGetTypeID(mimeTypeDescription) != CFStringGetTypeID())
15265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            mimeTypeDescription = 0;
15365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
15465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        mimeClassInfo.type = String(mimeType).lower();
15565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        mimeClassInfo.desc = mimeTypeDescription;
15665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
15765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Now get the extensions for this MIME type.
15865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        CFIndex numExtensions = 0;
15965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        CFArrayRef extensionsArray = static_cast<CFArrayRef>(CFDictionaryGetValue(mimeTypeInfo, CFSTR("WebPluginExtensions")));
16065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (extensionsArray && CFGetTypeID(extensionsArray) == CFArrayGetTypeID())
16165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            numExtensions = CFArrayGetCount(extensionsArray);
16265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
16365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        for (CFIndex i = 0; i < numExtensions; ++i) {
16465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            CFStringRef extension = static_cast<CFStringRef>(CFArrayGetValueAtIndex(extensionsArray, i));
16565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            if (!extension || CFGetTypeID(extension) != CFStringGetTypeID())
16665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                continue;
1672bde8e466a4451c7319e3a072d118917957d6554Steve Block
1682bde8e466a4451c7319e3a072d118917957d6554Steve Block            // The DivX plug-in lists multiple extensions in a comma separated string instead of using
1692bde8e466a4451c7319e3a072d118917957d6554Steve Block            // multiple array elements in the property list. Work around this here by splitting the
1702bde8e466a4451c7319e3a072d118917957d6554Steve Block            // extension string into components.
1712bde8e466a4451c7319e3a072d118917957d6554Steve Block            Vector<String> extensionComponents;
1722bde8e466a4451c7319e3a072d118917957d6554Steve Block            String(extension).lower().split(',', extensionComponents);
1732bde8e466a4451c7319e3a072d118917957d6554Steve Block
1742bde8e466a4451c7319e3a072d118917957d6554Steve Block            for (size_t i = 0; i < extensionComponents.size(); ++i)
1752bde8e466a4451c7319e3a072d118917957d6554Steve Block                mimeClassInfo.extensions.append(extensionComponents[i]);
17665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        }
17765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
17865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Add this MIME type.
17965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        pluginInfo.mimes.append(mimeClassInfo);
18065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
18165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
18265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return true;
18365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
18465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
18565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochclass ResourceMap {
18665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochpublic:
18765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    explicit ResourceMap(CFBundleRef bundle)
18865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        : m_bundle(bundle)
18965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        , m_currentResourceFile(CurResFile())
19065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        , m_bundleResourceMap(CFBundleOpenBundleResourceMap(m_bundle))
19165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    {
19265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        UseResFile(m_bundleResourceMap);
19365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
19465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
19565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ~ResourceMap()
19665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    {
19765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Close the resource map.
19865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        CFBundleCloseBundleResourceMap(m_bundle, m_bundleResourceMap);
19965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
20065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // And restore the old resource.
20165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        UseResFile(m_currentResourceFile);
20265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
20365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
20465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    bool isValid() const { return m_bundleResourceMap != -1; }
20565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
20665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochprivate:
20765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    CFBundleRef m_bundle;
20865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ResFileRefNum m_currentResourceFile;
20965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ResFileRefNum m_bundleResourceMap;
21065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch};
21165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
21265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic bool getStringListResource(ResID resourceID, Vector<String>& stringList) {
21365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Handle stringListHandle = Get1Resource('STR#', resourceID);
21465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!stringListHandle || !*stringListHandle)
21565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
21665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
21765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Get the string list size.
21865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Size stringListSize = GetHandleSize(stringListHandle);
21965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (stringListSize < static_cast<Size>(sizeof(UInt16)))
22065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
22165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
22265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    CFStringEncoding stringEncoding = stringEncodingForResource(stringListHandle);
22365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
22465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    unsigned char* ptr = reinterpret_cast<unsigned char*>(*stringListHandle);
22565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    unsigned char* end = ptr + stringListSize;
22665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
22765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Get the number of strings in the string list.
22865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    UInt16 numStrings = *reinterpret_cast<UInt16*>(ptr);
22965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ptr += sizeof(UInt16);
23065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
23165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    for (UInt16 i = 0; i < numStrings; ++i) {
23265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // We're past the end of the string, bail.
23365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (ptr >= end)
23465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            return false;
23565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
23665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Get the string length.
23765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        unsigned char stringLength = *ptr++;
23865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
23965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        RetainPtr<CFStringRef> cfString(AdoptCF, CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, ptr, stringLength, stringEncoding, false, kCFAllocatorNull));
24065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (!cfString.get())
24165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            return false;
24265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
24365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        stringList.append(cfString.get());
24465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        ptr += stringLength;
24565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
24665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
24765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (ptr != end)
24865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
24965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
25065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return true;
25165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
25265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
25365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const ResID PluginNameOrDescriptionStringNumber = 126;
25465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const ResID MIMEDescriptionStringNumber = 127;
25565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const ResID MIMEListStringStringNumber = 128;
25665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
25765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic bool getPluginInfoFromCarbonResources(CFBundleRef bundle, PluginInfo& pluginInfo)
25865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
25965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ResourceMap resourceMap(bundle);
26065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!resourceMap.isValid())
26165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
26265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
26365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Get the description and name string list.
26465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Vector<String> descriptionAndName;
26565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!getStringListResource(PluginNameOrDescriptionStringNumber, descriptionAndName))
26665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
26765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
26865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Get the MIME types and extensions string list. This list needs to be a multiple of two.
26965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Vector<String> mimeTypesAndExtensions;
27065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!getStringListResource(MIMEListStringStringNumber, mimeTypesAndExtensions))
27165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
27265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
27365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (mimeTypesAndExtensions.size() % 2)
27465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
27565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
27665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Now get the MIME type descriptions string list. This string list needs to be the same length as the number of MIME types.
27765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Vector<String> mimeTypeDescriptions;
27865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!getStringListResource(MIMEDescriptionStringNumber, mimeTypeDescriptions))
27965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
28065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
28165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Add all MIME types.
28265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    for (size_t i = 0; i < mimeTypesAndExtensions.size() / 2; ++i) {
28365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        MimeClassInfo mimeClassInfo;
28465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
28565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        const String& mimeType = mimeTypesAndExtensions[i * 2];
2862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        String description;
2872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (i < mimeTypeDescriptions.size())
2882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            description = mimeTypeDescriptions[i];
28965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
29065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        mimeClassInfo.type = mimeType.lower();
29165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        mimeClassInfo.desc = description;
29265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
29365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        Vector<String> extensions;
29465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        mimeTypesAndExtensions[i * 2 + 1].split(',', extensions);
29565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
29665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        for (size_t i = 0; i < extensions.size(); ++i)
29765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            mimeClassInfo.extensions.append(extensions[i].lower());
29865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
29965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        pluginInfo.mimes.append(mimeClassInfo);
30065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
30165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
30265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Set the description and name if they exist.
30365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (descriptionAndName.size() > 0)
30465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        pluginInfo.desc = descriptionAndName[0];
30565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (descriptionAndName.size() > 1)
30665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        pluginInfo.name = descriptionAndName[1];
30765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
30865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return true;
30965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
31065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
31165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochbool NetscapePluginModule::getPluginInfo(const String& pluginPath, PluginInfoStore::Plugin& plugin)
31265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
31365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    RetainPtr<CFStringRef> bundlePath(AdoptCF, pluginPath.createCFString());
31465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    RetainPtr<CFURLRef> bundleURL(AdoptCF, CFURLCreateWithFileSystemPath(kCFAllocatorDefault, bundlePath.get(), kCFURLPOSIXPathStyle, false));
31565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
31665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Try to initialize the bundle.
31765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    RetainPtr<CFBundleRef> bundle(AdoptCF, CFBundleCreate(kCFAllocatorDefault, bundleURL.get()));
31865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!bundle)
31965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
32065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
32165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Check if this bundle is an NPAPI plug-in.
32265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    UInt32 packageType = 0;
32365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    CFBundleGetPackageInfo(bundle.get(), &packageType, 0);
32465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (packageType != FOUR_CHAR_CODE('BRPL'))
32565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
32665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
32765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Check that the architecture is valid.
32865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    cpu_type_t pluginArchitecture = 0;
32965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!getPluginArchitecture(bundle.get(), pluginArchitecture))
33065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
33165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
33265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Check that there's valid info for this plug-in.
33365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!getPluginInfoFromPropertyLists(bundle.get(), plugin.info) &&
33465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        !getPluginInfoFromCarbonResources(bundle.get(), plugin.info))
33565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
33665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
33765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    plugin.path = pluginPath;
33865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    plugin.pluginArchitecture = pluginArchitecture;
33965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    plugin.bundleIdentifier = CFBundleGetIdentifier(bundle.get());
34065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    plugin.versionNumber = CFBundleGetVersionNumber(bundle.get());
34165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
34265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    RetainPtr<CFStringRef> filename(AdoptCF, CFURLCopyLastPathComponent(bundleURL.get()));
34365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    plugin.info.file = filename.get();
34465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
34565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (plugin.info.name.isNull())
34665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        plugin.info.name = plugin.info.file;
34765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (plugin.info.desc.isNull())
34865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        plugin.info.desc = plugin.info.file;
34965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
35065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return true;
35165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
35265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
35365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginModule::determineQuirks()
35465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
35565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    PluginInfoStore::Plugin plugin;
35665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!getPluginInfo(m_pluginPath, plugin))
35765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return;
35865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
35965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (plugin.bundleIdentifier == "com.macromedia.Flash Player.plugin") {
36065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Flash requires that the return value of getprogname() be "WebKitPluginHost".
36165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        m_pluginQuirks.add(PluginQuirks::PrognameShouldBeWebKitPluginHost);
3622bde8e466a4451c7319e3a072d118917957d6554Steve Block
3632bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Flash supports snapshotting.
36481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        m_pluginQuirks.add(PluginQuirks::SupportsSnapshotting);
36565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
3662bde8e466a4451c7319e3a072d118917957d6554Steve Block
3672bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (plugin.bundleIdentifier == "com.microsoft.SilverlightPlugin") {
3682bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Silverlight doesn't explicitly opt into transparency, so we'll do it whenever
3692bde8e466a4451c7319e3a072d118917957d6554Steve Block        // there's a 'background' attribute.
3702bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_pluginQuirks.add(PluginQuirks::MakeTransparentIfBackgroundAttributeExists);
3712bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3722bde8e466a4451c7319e3a072d118917957d6554Steve Block
3732bde8e466a4451c7319e3a072d118917957d6554Steve Block#ifndef NP_NO_QUICKDRAW
3742bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (plugin.bundleIdentifier == "com.apple.ist.ds.appleconnect.webplugin") {
3752bde8e466a4451c7319e3a072d118917957d6554Steve Block        // The AppleConnect plug-in uses QuickDraw but doesn't paint or receive events
3762bde8e466a4451c7319e3a072d118917957d6554Steve Block        // so we'll allow it to be instantiated even though we don't support QuickDraw.
3772bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_pluginQuirks.add(PluginQuirks::AllowHalfBakedQuickDrawSupport);
3782bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3792bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif
38065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
38165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
38265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch} // namespace WebKit
383