diff options
Diffstat (limited to 'webkit/glue/plugins/plugin_lib_posix.cc')
-rw-r--r-- | webkit/glue/plugins/plugin_lib_posix.cc | 256 |
1 files changed, 0 insertions, 256 deletions
diff --git a/webkit/glue/plugins/plugin_lib_posix.cc b/webkit/glue/plugins/plugin_lib_posix.cc deleted file mode 100644 index ac937e1..0000000 --- a/webkit/glue/plugins/plugin_lib_posix.cc +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "webkit/glue/plugins/plugin_lib.h" - -#include <dlfcn.h> -#if defined(OS_OPENBSD) -#include <sys/exec_elf.h> -#else -#include <elf.h> -#include <fcntl.h> -#endif -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include "base/eintr_wrapper.h" -#include "base/file_util.h" -#include "base/string_split.h" -#include "base/string_util.h" -#include "base/sys_string_conversions.h" -#include "base/utf_string_conversions.h" -#include "webkit/glue/plugins/plugin_list.h" - -// These headers must be included in this order to make the declaration gods -// happy. -#include "base/third_party/nspr/prcpucfg_linux.h" - -namespace { - -using NPAPI::PluginList; - -// Copied from nsplugindefs.h instead of including the file since it has a bunch -// of dependencies. -enum nsPluginVariable { - nsPluginVariable_NameString = 1, - nsPluginVariable_DescriptionString = 2 -}; - -// Read the ELF header and return true if it is usable on -// the current architecture (e.g. 32-bit ELF on 32-bit build). -// Returns false on other errors as well. -bool ELFMatchesCurrentArchitecture(const FilePath& filename) { - // First make sure we can open the file and it is in fact, a regular file. - struct stat stat_buf; - // Open with O_NONBLOCK so we don't block on pipes. - int fd = open(filename.value().c_str(), O_RDONLY|O_NONBLOCK); - if (fd < 0) - return false; - bool ret = (fstat(fd, &stat_buf) >= 0 && S_ISREG(stat_buf.st_mode)); - if (HANDLE_EINTR(close(fd)) < 0) - return false; - if (!ret) - return false; - - const size_t kELFBufferSize = 5; - char buffer[kELFBufferSize]; - if (!file_util::ReadFile(filename, buffer, kELFBufferSize)) - return false; - - if (buffer[0] != ELFMAG0 || - buffer[1] != ELFMAG1 || - buffer[2] != ELFMAG2 || - buffer[3] != ELFMAG3) { - // Not an ELF file, perhaps? - return false; - } - - int elf_class = buffer[EI_CLASS]; -#if defined(ARCH_CPU_32_BITS) - if (elf_class == ELFCLASS32) - return true; -#elif defined(ARCH_CPU_64_BITS) - if (elf_class == ELFCLASS64) - return true; -#endif - - return false; -} - -// This structure matches enough of nspluginwrapper's NPW_PluginInfo -// for us to extract the real plugin path. -struct __attribute__((packed)) NSPluginWrapperInfo { - char ident[32]; // NSPluginWrapper magic identifier (includes version). - char path[PATH_MAX]; // Path to wrapped plugin. -}; - -// Test a plugin for whether it's been wrapped by NSPluginWrapper, and -// if so attempt to unwrap it. Pass in an opened plugin handle; on -// success, |dl| and |unwrapped_path| will be filled in with the newly -// opened plugin. On failure, params are left unmodified. -void UnwrapNSPluginWrapper(void **dl, FilePath* unwrapped_path) { - NSPluginWrapperInfo* info = - reinterpret_cast<NSPluginWrapperInfo*>(dlsym(*dl, "NPW_Plugin")); - if (!info) - return; // Not a NSPW plugin. - - // Here we could check the NSPW ident field for the versioning - // information, but the path field is available in all versions - // anyway. - - // Grab the path to the wrapped plugin. Just in case the structure - // format changes, protect against the path not being null-terminated. - char* path_end = static_cast<char*>(memchr(info->path, '\0', - sizeof(info->path))); - if (!path_end) - path_end = info->path + sizeof(info->path); - FilePath path = FilePath(std::string(info->path, path_end - info->path)); - - if (!ELFMatchesCurrentArchitecture(path)) { - LOG(WARNING) << path.value() << " is nspluginwrapper wrapping a " - << "plugin for a different architecture; it will " - << "work better if you instead use a native plugin."; - return; - } - - void* newdl = base::LoadNativeLibrary(path); - if (!newdl) { - // We couldn't load the unwrapped plugin for some reason, despite - // being able to load the wrapped one. Just use the wrapped one. - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "Could not use unwrapped nspluginwrapper plugin " - << unwrapped_path->value() << ", using the wrapped one."; - return; - } - - // Unload the wrapped plugin, and use the wrapped plugin instead. - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "Using unwrapped version " << unwrapped_path->value() - << " of nspluginwrapper-wrapped plugin."; - base::UnloadNativeLibrary(*dl); - *dl = newdl; - *unwrapped_path = path; -} - -} // anonymous namespace - -namespace NPAPI { - -bool PluginLib::ReadWebPluginInfo(const FilePath& filename, - WebPluginInfo* info) { - // The file to reference is: - // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUnix.cpp - - // Skip files that aren't appropriate for our architecture. - if (!ELFMatchesCurrentArchitecture(filename)) { - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "Skipping plugin " << filename.value() - << " because it doesn't match the current architecture."; - return false; - } - - void* dl = base::LoadNativeLibrary(filename); - if (!dl) { - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "While reading plugin info, unable to load library " - << filename.value() << ", skipping."; - return false; - } - - info->path = filename; - info->enabled = true; - - // Attempt to swap in the wrapped plugin if this is nspluginwrapper. - UnwrapNSPluginWrapper(&dl, &info->path); - - // See comments in plugin_lib_mac regarding this symbol. - typedef const char* (*NP_GetMimeDescriptionType)(); - NP_GetMimeDescriptionType NP_GetMIMEDescription = - reinterpret_cast<NP_GetMimeDescriptionType>( - dlsym(dl, "NP_GetMIMEDescription")); - const char* mime_description = NULL; - if (NP_GetMIMEDescription) - mime_description = NP_GetMIMEDescription(); - - if (mime_description) - ParseMIMEDescription(mime_description, &info->mime_types); - - // The plugin name and description live behind NP_GetValue calls. - typedef NPError (*NP_GetValueType)(void* unused, - nsPluginVariable variable, - void* value_out); - NP_GetValueType NP_GetValue = - reinterpret_cast<NP_GetValueType>(dlsym(dl, "NP_GetValue")); - if (NP_GetValue) { - const char* name = NULL; - NP_GetValue(NULL, nsPluginVariable_NameString, &name); - if (name) - info->name = UTF8ToUTF16(name); - - const char* description = NULL; - NP_GetValue(NULL, nsPluginVariable_DescriptionString, &description); - if (description) - info->desc = UTF8ToUTF16(description); - - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "Got info for plugin " << filename.value() - << " Name = \"" << UTF16ToUTF8(info->name) - << "\", Description = \"" << UTF16ToUTF8(info->desc) << "\"."; - } else { - LOG_IF(ERROR, PluginList::DebugPluginLoading()) - << "Plugin " << filename.value() - << " has no GetValue() and probably won't work."; - } - - // Intentionally not unloading the plugin here, it can lead to crashes. - - return true; -} - -// static -void PluginLib::ParseMIMEDescription( - const std::string& description, - std::vector<WebPluginMimeType>* mime_types) { - // We parse the description here into WebPluginMimeType structures. - // Naively from the NPAPI docs you'd think you could use - // string-splitting, but the Firefox parser turns out to do something - // different: find the first colon, then the second, then a semi. - // - // See ParsePluginMimeDescription near - // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUtils.h#53 - - std::string::size_type ofs = 0; - for (;;) { - WebPluginMimeType mime_type; - - std::string::size_type end = description.find(':', ofs); - if (end == std::string::npos) - break; - mime_type.mime_type = description.substr(ofs, end - ofs); - ofs = end + 1; - - end = description.find(':', ofs); - if (end == std::string::npos) - break; - const std::string extensions = description.substr(ofs, end - ofs); - base::SplitString(extensions, ',', &mime_type.file_extensions); - ofs = end + 1; - - end = description.find(';', ofs); - // It's ok for end to run off the string here. If there's no - // trailing semicolon we consume the remainder of the string. - if (end != std::string::npos) { - mime_type.description = UTF8ToUTF16(description.substr(ofs, end - ofs)); - } else { - mime_type.description = UTF8ToUTF16(description.substr(ofs)); - } - mime_types->push_back(mime_type); - if (end == std::string::npos) - break; - ofs = end + 1; - } -} - -} // namespace NPAPI |