diff options
Diffstat (limited to 'Source/WebKit2/Shared/Plugins/Netscape')
5 files changed, 784 insertions, 0 deletions
diff --git a/Source/WebKit2/Shared/Plugins/Netscape/NetscapePluginModule.cpp b/Source/WebKit2/Shared/Plugins/Netscape/NetscapePluginModule.cpp new file mode 100644 index 0000000..fec00b3 --- /dev/null +++ b/Source/WebKit2/Shared/Plugins/Netscape/NetscapePluginModule.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "NetscapePluginModule.h" + +#include "Module.h" +#include "NetscapeBrowserFuncs.h" +#include <wtf/PassOwnPtr.h> + +namespace WebKit { + +static Vector<NetscapePluginModule*>& initializedNetscapePluginModules() +{ + DEFINE_STATIC_LOCAL(Vector<NetscapePluginModule*>, initializedNetscapePluginModules, ()); + return initializedNetscapePluginModules; +} + +NetscapePluginModule::NetscapePluginModule(const String& pluginPath) + : m_pluginPath(pluginPath) + , m_isInitialized(false) + , m_pluginCount(0) + , m_shutdownProcPtr(0) + , m_pluginFuncs() +{ +} + +NetscapePluginModule::~NetscapePluginModule() +{ + ASSERT(initializedNetscapePluginModules().find(this) == notFound); +} + +void NetscapePluginModule::pluginCreated() +{ + if (!m_pluginCount) { + // Load the plug-in module if necessary. + load(); + } + + m_pluginCount++; +} + +void NetscapePluginModule::pluginDestroyed() +{ + ASSERT(m_pluginCount > 0); + m_pluginCount--; + + if (!m_pluginCount) { + shutdown(); + unload(); + } +} + +void NetscapePluginModule::shutdown() +{ + ASSERT(m_isInitialized); + + m_shutdownProcPtr(); + + m_isInitialized = false; + + size_t pluginModuleIndex = initializedNetscapePluginModules().find(this); + ASSERT(pluginModuleIndex != notFound); + + initializedNetscapePluginModules().remove(pluginModuleIndex); +} + +PassRefPtr<NetscapePluginModule> NetscapePluginModule::getOrCreate(const String& pluginPath) +{ + // First, see if we already have a module with this plug-in path. + for (size_t i = 0; i < initializedNetscapePluginModules().size(); ++i) { + NetscapePluginModule* pluginModule = initializedNetscapePluginModules()[i]; + + if (pluginModule->m_pluginPath == pluginPath) + return pluginModule; + } + + RefPtr<NetscapePluginModule> pluginModule(adoptRef(new NetscapePluginModule(pluginPath))); + + // Try to load and initialize the plug-in module. + if (!pluginModule->load()) + return 0; + + return pluginModule.release(); +} + +bool NetscapePluginModule::load() +{ + if (m_isInitialized) { + ASSERT(initializedNetscapePluginModules().find(this) != notFound); + return true; + } + + if (!tryLoad()) { + unload(); + return false; + } + + m_isInitialized = true; + + ASSERT(initializedNetscapePluginModules().find(this) == notFound); + initializedNetscapePluginModules().append(this); + + determineQuirks(); + + return true; +} + +bool NetscapePluginModule::tryLoad() +{ + m_module = adoptPtr(new Module(m_pluginPath)); + if (!m_module->load()) + return false; + + NP_InitializeFuncPtr initializeFuncPtr = m_module->functionPointer<NP_InitializeFuncPtr>("NP_Initialize"); + if (!initializeFuncPtr) + return false; + + NP_GetEntryPointsFuncPtr getEntryPointsFuncPtr = m_module->functionPointer<NP_GetEntryPointsFuncPtr>("NP_GetEntryPoints"); + if (!getEntryPointsFuncPtr) + return false; + + m_shutdownProcPtr = m_module->functionPointer<NPP_ShutdownProcPtr>("NP_Shutdown"); + if (!m_shutdownProcPtr) + return false; + + m_pluginFuncs.size = sizeof(NPPluginFuncs); + m_pluginFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; + + // On Mac, NP_Initialize must be called first, then NP_GetEntryPoints. On Windows, the order is + // reversed. Failing to follow this order results in crashes (e.g., in Silverlight on Mac and + // in Flash and QuickTime on Windows). +#if PLATFORM(MAC) + if (initializeFuncPtr(netscapeBrowserFuncs()) != NPERR_NO_ERROR || getEntryPointsFuncPtr(&m_pluginFuncs) != NPERR_NO_ERROR) + return false; +#elif PLATFORM(WIN) + if (getEntryPointsFuncPtr(&m_pluginFuncs) != NPERR_NO_ERROR || initializeFuncPtr(netscapeBrowserFuncs()) != NPERR_NO_ERROR) + return false; +#endif + + return true; +} + +void NetscapePluginModule::unload() +{ + ASSERT(!m_isInitialized); + + m_module = 0; +} + +} // namespace WebKit + diff --git a/Source/WebKit2/Shared/Plugins/Netscape/NetscapePluginModule.h b/Source/WebKit2/Shared/Plugins/Netscape/NetscapePluginModule.h new file mode 100644 index 0000000..a245b11 --- /dev/null +++ b/Source/WebKit2/Shared/Plugins/Netscape/NetscapePluginModule.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NetscapePluginModule_h +#define NetscapePluginModule_h + +#include "Module.h" +#include "PluginQuirks.h" +#include <WebCore/npfunctions.h> +#include <wtf/RefCounted.h> +#include <wtf/text/WTFString.h> + +// FIXME: We should not include PluginInfoStore.h here. Instead, +// PluginInfoStore::Plugin should be moved out into its own header which we can +// put in Shared/Plugins. +#include "PluginInfoStore.h" + +namespace WebKit { + +class NetscapePluginModule : public RefCounted<NetscapePluginModule> { +public: + static PassRefPtr<NetscapePluginModule> getOrCreate(const String& pluginPath); + ~NetscapePluginModule(); + + const NPPluginFuncs& pluginFuncs() const { return m_pluginFuncs; } + + void pluginCreated(); + void pluginDestroyed(); + + static bool getPluginInfo(const String& pluginPath, PluginInfoStore::Plugin&); + + const PluginQuirks& pluginQuirks() const { return m_pluginQuirks; } + +private: + explicit NetscapePluginModule(const String& pluginPath); + + void determineQuirks(); + + bool tryLoad(); + bool load(); + void unload(); + + void shutdown(); + + String m_pluginPath; + bool m_isInitialized; + unsigned m_pluginCount; + + PluginQuirks m_pluginQuirks; + + NPP_ShutdownProcPtr m_shutdownProcPtr; + NPPluginFuncs m_pluginFuncs; + + OwnPtr<Module> m_module; +}; + +} // namespace WebKit + +#endif // NetscapePluginModule_h diff --git a/Source/WebKit2/Shared/Plugins/Netscape/mac/NetscapePluginModuleMac.mm b/Source/WebKit2/Shared/Plugins/Netscape/mac/NetscapePluginModuleMac.mm new file mode 100644 index 0000000..6ecacf0 --- /dev/null +++ b/Source/WebKit2/Shared/Plugins/Netscape/mac/NetscapePluginModuleMac.mm @@ -0,0 +1,338 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "NetscapePluginModule.h" + +#include <WebCore/WebCoreNSStringExtras.h> +#include <wtf/HashSet.h> + +using namespace WebCore; + +namespace WebKit { + +static bool getPluginArchitecture(CFBundleRef bundle, cpu_type_t& pluginArchitecture) +{ + RetainPtr<CFArrayRef> pluginArchitecturesArray(AdoptCF, CFBundleCopyExecutableArchitectures(bundle)); + if (!pluginArchitecturesArray) + return false; + + // Turn the array into a set. + HashSet<unsigned> architectures; + for (CFIndex i = 0, numPluginArchitectures = CFArrayGetCount(pluginArchitecturesArray.get()); i < numPluginArchitectures; ++i) { + CFNumberRef number = static_cast<CFNumberRef>(CFArrayGetValueAtIndex(pluginArchitecturesArray.get(), i)); + + SInt32 architecture; + if (!CFNumberGetValue(number, kCFNumberSInt32Type, &architecture)) + continue; + architectures.add(architecture); + } + +#ifdef __x86_64__ + // We only support 64-bit Intel plug-ins on 64-bit Intel. + if (architectures.contains(kCFBundleExecutableArchitectureX86_64)) { + pluginArchitecture = CPU_TYPE_X86_64; + return true; + } + + // We also support 32-bit Intel plug-ins on 64-bit Intel. + if (architectures.contains(kCFBundleExecutableArchitectureI386)) { + pluginArchitecture = CPU_TYPE_X86; + return true; + } +#elif defined(__i386__) + // We only support 32-bit Intel plug-ins on 32-bit Intel. + if (architectures.contains(kCFBundleExecutableArchitectureI386)) { + pluginArchitecture = CPU_TYPE_X86; + return true; + } +#elif defined(__ppc64__) + // We only support 64-bit PPC plug-ins on 64-bit PPC. + if (architectures.contains(kCFBundleExecutableArchitecturePPC64)) { + pluginArchitecture = CPU_TYPE_POWERPC64; + return true; + } +#elif defined(__ppc__) + // We only support 32-bit PPC plug-ins on 32-bit PPC. + if (architectures.contains(kCFBundleExecutableArchitecturePPC)) { + pluginArchitecture = CPU_TYPE_POWERPC; + return true; + } +#else +#error "Unhandled architecture" +#endif + + return false; +} + +static bool getPluginInfoFromPropertyLists(CFBundleRef bundle, PluginInfo& pluginInfo) +{ + // FIXME: Handle WebPluginMIMETypesFilenameKey. + + CFDictionaryRef mimeTypes = static_cast<CFDictionaryRef>(CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginMIMETypes"))); + if (!mimeTypes || CFGetTypeID(mimeTypes) != CFDictionaryGetTypeID()) + return false; + + // Get the plug-in name. + CFStringRef pluginName = static_cast<CFStringRef>(CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginName"))); + if (pluginName && CFGetTypeID(pluginName) == CFStringGetTypeID()) + pluginInfo.name = pluginName; + + // Get the plug-in description. + CFStringRef pluginDescription = static_cast<CFStringRef>(CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginDescription"))); + if (pluginDescription && CFGetTypeID(pluginDescription) == CFStringGetTypeID()) + pluginInfo.desc = pluginDescription; + + // Get the MIME type mapping dictionary. + CFIndex numMimeTypes = CFDictionaryGetCount(mimeTypes); + Vector<CFStringRef> mimeTypesVector(numMimeTypes); + Vector<CFDictionaryRef> mimeTypeInfoVector(numMimeTypes); + CFDictionaryGetKeysAndValues(mimeTypes, reinterpret_cast<const void**>(mimeTypesVector.data()), reinterpret_cast<const void**>(mimeTypeInfoVector.data())); + + for (CFIndex i = 0; i < numMimeTypes; ++i) { + MimeClassInfo mimeClassInfo; + + // If this MIME type is invalid, ignore it. + CFStringRef mimeType = mimeTypesVector[i]; + if (!mimeType || CFGetTypeID(mimeType) != CFStringGetTypeID() || CFStringGetLength(mimeType) == 0) + continue; + + // If this MIME type doesn't have a valid info dictionary, ignore it. + CFDictionaryRef mimeTypeInfo = mimeTypeInfoVector[i]; + if (!mimeTypeInfo || CFGetTypeID(mimeTypeInfo) != CFDictionaryGetTypeID()) + continue; + + // Get the MIME type description. + CFStringRef mimeTypeDescription = static_cast<CFStringRef>(CFDictionaryGetValue(mimeTypeInfo, CFSTR("WebPluginTypeDescription"))); + if (mimeTypeDescription && CFGetTypeID(mimeTypeDescription) != CFStringGetTypeID()) + mimeTypeDescription = 0; + + mimeClassInfo.type = String(mimeType).lower(); + mimeClassInfo.desc = mimeTypeDescription; + + // Now get the extensions for this MIME type. + CFIndex numExtensions = 0; + CFArrayRef extensionsArray = static_cast<CFArrayRef>(CFDictionaryGetValue(mimeTypeInfo, CFSTR("WebPluginExtensions"))); + if (extensionsArray && CFGetTypeID(extensionsArray) == CFArrayGetTypeID()) + numExtensions = CFArrayGetCount(extensionsArray); + + for (CFIndex i = 0; i < numExtensions; ++i) { + CFStringRef extension = static_cast<CFStringRef>(CFArrayGetValueAtIndex(extensionsArray, i)); + if (!extension || CFGetTypeID(extension) != CFStringGetTypeID()) + continue; + + mimeClassInfo.extensions.append(String(extension).lower()); + } + + // Add this MIME type. + pluginInfo.mimes.append(mimeClassInfo); + } + + return true; +} + +class ResourceMap { +public: + explicit ResourceMap(CFBundleRef bundle) + : m_bundle(bundle) + , m_currentResourceFile(CurResFile()) + , m_bundleResourceMap(CFBundleOpenBundleResourceMap(m_bundle)) + { + UseResFile(m_bundleResourceMap); + } + + ~ResourceMap() + { + // Close the resource map. + CFBundleCloseBundleResourceMap(m_bundle, m_bundleResourceMap); + + // And restore the old resource. + UseResFile(m_currentResourceFile); + } + + bool isValid() const { return m_bundleResourceMap != -1; } + +private: + CFBundleRef m_bundle; + ResFileRefNum m_currentResourceFile; + ResFileRefNum m_bundleResourceMap; +}; + +static bool getStringListResource(ResID resourceID, Vector<String>& stringList) { + Handle stringListHandle = Get1Resource('STR#', resourceID); + if (!stringListHandle || !*stringListHandle) + return false; + + // Get the string list size. + Size stringListSize = GetHandleSize(stringListHandle); + if (stringListSize < static_cast<Size>(sizeof(UInt16))) + return false; + + CFStringEncoding stringEncoding = stringEncodingForResource(stringListHandle); + + unsigned char* ptr = reinterpret_cast<unsigned char*>(*stringListHandle); + unsigned char* end = ptr + stringListSize; + + // Get the number of strings in the string list. + UInt16 numStrings = *reinterpret_cast<UInt16*>(ptr); + ptr += sizeof(UInt16); + + for (UInt16 i = 0; i < numStrings; ++i) { + // We're past the end of the string, bail. + if (ptr >= end) + return false; + + // Get the string length. + unsigned char stringLength = *ptr++; + + RetainPtr<CFStringRef> cfString(AdoptCF, CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, ptr, stringLength, stringEncoding, false, kCFAllocatorNull)); + if (!cfString.get()) + return false; + + stringList.append(cfString.get()); + ptr += stringLength; + } + + if (ptr != end) + return false; + + return true; +} + +static const ResID PluginNameOrDescriptionStringNumber = 126; +static const ResID MIMEDescriptionStringNumber = 127; +static const ResID MIMEListStringStringNumber = 128; + +static bool getPluginInfoFromCarbonResources(CFBundleRef bundle, PluginInfo& pluginInfo) +{ + ResourceMap resourceMap(bundle); + if (!resourceMap.isValid()) + return false; + + // Get the description and name string list. + Vector<String> descriptionAndName; + if (!getStringListResource(PluginNameOrDescriptionStringNumber, descriptionAndName)) + return false; + + // Get the MIME types and extensions string list. This list needs to be a multiple of two. + Vector<String> mimeTypesAndExtensions; + if (!getStringListResource(MIMEListStringStringNumber, mimeTypesAndExtensions)) + return false; + + if (mimeTypesAndExtensions.size() % 2) + return false; + + size_t numMimeTypes = mimeTypesAndExtensions.size() / 2; + + // Now get the MIME type descriptions string list. This string list needs to be the same length as the number of MIME types. + Vector<String> mimeTypeDescriptions; + if (!getStringListResource(MIMEDescriptionStringNumber, mimeTypeDescriptions)) + return false; + + if (mimeTypeDescriptions.size() != numMimeTypes) + return false; + + // Add all MIME types. + for (size_t i = 0; i < mimeTypesAndExtensions.size() / 2; ++i) { + MimeClassInfo mimeClassInfo; + + const String& mimeType = mimeTypesAndExtensions[i * 2]; + const String& description = mimeTypeDescriptions[i]; + + mimeClassInfo.type = mimeType.lower(); + mimeClassInfo.desc = description; + + Vector<String> extensions; + mimeTypesAndExtensions[i * 2 + 1].split(',', extensions); + + for (size_t i = 0; i < extensions.size(); ++i) + mimeClassInfo.extensions.append(extensions[i].lower()); + + pluginInfo.mimes.append(mimeClassInfo); + } + + // Set the description and name if they exist. + if (descriptionAndName.size() > 0) + pluginInfo.desc = descriptionAndName[0]; + if (descriptionAndName.size() > 1) + pluginInfo.name = descriptionAndName[1]; + + return true; +} + +bool NetscapePluginModule::getPluginInfo(const String& pluginPath, PluginInfoStore::Plugin& plugin) +{ + RetainPtr<CFStringRef> bundlePath(AdoptCF, pluginPath.createCFString()); + RetainPtr<CFURLRef> bundleURL(AdoptCF, CFURLCreateWithFileSystemPath(kCFAllocatorDefault, bundlePath.get(), kCFURLPOSIXPathStyle, false)); + + // Try to initialize the bundle. + RetainPtr<CFBundleRef> bundle(AdoptCF, CFBundleCreate(kCFAllocatorDefault, bundleURL.get())); + if (!bundle) + return false; + + // Check if this bundle is an NPAPI plug-in. + UInt32 packageType = 0; + CFBundleGetPackageInfo(bundle.get(), &packageType, 0); + if (packageType != FOUR_CHAR_CODE('BRPL')) + return false; + + // Check that the architecture is valid. + cpu_type_t pluginArchitecture = 0; + if (!getPluginArchitecture(bundle.get(), pluginArchitecture)) + return false; + + // Check that there's valid info for this plug-in. + if (!getPluginInfoFromPropertyLists(bundle.get(), plugin.info) && + !getPluginInfoFromCarbonResources(bundle.get(), plugin.info)) + return false; + + plugin.path = pluginPath; + plugin.pluginArchitecture = pluginArchitecture; + plugin.bundleIdentifier = CFBundleGetIdentifier(bundle.get()); + plugin.versionNumber = CFBundleGetVersionNumber(bundle.get()); + + RetainPtr<CFStringRef> filename(AdoptCF, CFURLCopyLastPathComponent(bundleURL.get())); + plugin.info.file = filename.get(); + + if (plugin.info.name.isNull()) + plugin.info.name = plugin.info.file; + if (plugin.info.desc.isNull()) + plugin.info.desc = plugin.info.file; + + return true; +} + +void NetscapePluginModule::determineQuirks() +{ + PluginInfoStore::Plugin plugin; + if (!getPluginInfo(m_pluginPath, plugin)) + return; + + if (plugin.bundleIdentifier == "com.macromedia.Flash Player.plugin") { + // Flash requires that the return value of getprogname() be "WebKitPluginHost". + m_pluginQuirks.add(PluginQuirks::PrognameShouldBeWebKitPluginHost); + } +} + +} // namespace WebKit diff --git a/Source/WebKit2/Shared/Plugins/Netscape/win/NetscapePluginModuleWin.cpp b/Source/WebKit2/Shared/Plugins/Netscape/win/NetscapePluginModuleWin.cpp new file mode 100644 index 0000000..f969ba4 --- /dev/null +++ b/Source/WebKit2/Shared/Plugins/Netscape/win/NetscapePluginModuleWin.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "NetscapePluginModule.h" + +#include <WebCore/FileSystem.h> +#include <wtf/OwnArrayPtr.h> + +using namespace WebCore; + +namespace WebKit { + +static String getVersionInfo(const LPVOID versionInfoData, const String& info) +{ + LPVOID buffer; + UINT bufferLength; + String subInfo = "\\StringfileInfo\\040904E4\\" + info; + if (!::VerQueryValueW(versionInfoData, const_cast<UChar*>(subInfo.charactersWithNullTermination()), &buffer, &bufferLength) || !bufferLength) + return String(); + + // Subtract 1 from the length; we don't want the trailing null character. + return String(reinterpret_cast<UChar*>(buffer), bufferLength - 1); +} + +static uint64_t fileVersion(DWORD leastSignificant, DWORD mostSignificant) +{ + ULARGE_INTEGER version; + version.LowPart = leastSignificant; + version.HighPart = mostSignificant; + return version.QuadPart; +} + +bool NetscapePluginModule::getPluginInfo(const String& pluginPath, PluginInfoStore::Plugin& plugin) +{ + String pathCopy = pluginPath; + DWORD versionInfoSize = ::GetFileVersionInfoSizeW(pathCopy.charactersWithNullTermination(), 0); + if (!versionInfoSize) + return false; + + OwnArrayPtr<char> versionInfoData(new char[versionInfoSize]); + if (!::GetFileVersionInfoW(pathCopy.charactersWithNullTermination(), 0, versionInfoSize, versionInfoData.get())) + return false; + + String name = getVersionInfo(versionInfoData.get(), "ProductName"); + String description = getVersionInfo(versionInfoData.get(), "FileDescription"); + if (name.isNull() || description.isNull()) + return false; + + VS_FIXEDFILEINFO* info; + UINT infoSize; + if (!::VerQueryValueW(versionInfoData.get(), L"\\", reinterpret_cast<void**>(&info), &infoSize) || infoSize < sizeof(VS_FIXEDFILEINFO)) + return false; + + Vector<String> types; + getVersionInfo(versionInfoData.get(), "MIMEType").split('|', types); + Vector<String> extensionLists; + getVersionInfo(versionInfoData.get(), "FileExtents").split('|', extensionLists); + Vector<String> descriptions; + getVersionInfo(versionInfoData.get(), "FileOpenName").split('|', descriptions); + + Vector<MimeClassInfo> mimes(types.size()); + for (size_t i = 0; i < types.size(); i++) { + String type = types[i].lower(); + String description = i < descriptions.size() ? descriptions[i] : ""; + String extensionList = i < extensionLists.size() ? extensionLists[i] : ""; + + Vector<String> extensionsVector; + extensionList.split(',', extensionsVector); + + // Get rid of the extension list that may be at the end of the description string. + int pos = description.find("(*"); + if (pos != -1) { + // There might be a space that we need to get rid of. + if (pos > 1 && description[pos - 1] == ' ') + pos--; + description = description.left(pos); + } + + mimes[i].type = type; + mimes[i].desc = description; + mimes[i].extensions.swap(extensionsVector); + } + + plugin.path = pluginPath; + plugin.info.desc = description; + plugin.info.name = name; + plugin.info.file = pathGetFileName(pluginPath); + plugin.info.mimes.swap(mimes); + plugin.fileVersion = fileVersion(info->dwFileVersionLS, info->dwFileVersionMS); + + return true; +} + +void NetscapePluginModule::determineQuirks() +{ +} + +} // namespace WebKit + diff --git a/Source/WebKit2/Shared/Plugins/Netscape/x11/NetscapePluginModuleX11.cpp b/Source/WebKit2/Shared/Plugins/Netscape/x11/NetscapePluginModuleX11.cpp new file mode 100644 index 0000000..a02cdad --- /dev/null +++ b/Source/WebKit2/Shared/Plugins/Netscape/x11/NetscapePluginModuleX11.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "NetscapePluginModule.h" + +#include "PluginDatabase.h" +#include "PluginPackage.h" + +using namespace WebCore; + +namespace WebKit { + +bool NetscapePluginModule::getPluginInfo(const String& pluginPath, PluginInfoStore::Plugin& plugin) +{ + // We are loading the plugin here since it does not seem to be a standardized way to + // get the needed informations from a UNIX plugin without loading it. + + RefPtr<PluginPackage> package = PluginPackage::createPackage(pluginPath, 0 /*lastModified*/); + if (!package) + return false; + + plugin.path = pluginPath; + plugin.info.desc = package->description(); + plugin.info.file = package->fileName(); + + const MIMEToDescriptionsMap& descriptions = package->mimeToDescriptions(); + const MIMEToExtensionsMap& extensions = package->mimeToExtensions(); + MIMEToDescriptionsMap::const_iterator descEnd = descriptions.end(); + plugin.info.mimes.reserveCapacity(descriptions.size()); + unsigned i = 0; + for (MIMEToDescriptionsMap::const_iterator it = descriptions.begin(); it != descEnd; ++it) { + plugin.info.mimes.uncheckedAppend(MimeClassInfo()); + MimeClassInfo& mime = plugin.info.mimes[i++]; + mime.type = it->first; + mime.desc = it->second; + MIMEToExtensionsMap::const_iterator extensionIt = extensions.find(it->first); + ASSERT(extensionIt != extensions.end()); + mime.extensions = extensionIt->second; + } + + package->unload(); + return true; +} + +void NetscapePluginModule::determineQuirks() +{ +} + +} // namespace WebKit |