| Index: webkit/glue/plugins/plugin_lib_posix.cc
|
| ===================================================================
|
| --- webkit/glue/plugins/plugin_lib_posix.cc (revision 69426)
|
| +++ webkit/glue/plugins/plugin_lib_posix.cc (working copy)
|
| @@ -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
|
|
|